#!/usr/bin/env python
# encoding: utf-8

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog,QPrintPreviewDialog
from PIL import Image
import xlwt
import xlrd
import xlsxwriter
from threading import Thread
from queue import Queue


import PyQt5_stylesheets
#  from images import images_rc
import os
import glob
import re
import win32api

import time
import serial
import serial.tools.list_ports
import binascii
import qtawesome as qta
from six import unichr
import numpy as np

import pyqtgraph as pg
pg.setConfigOption('background', '#E3E6E3')
pg.setConfigOption('foreground', 'k')
import pyqtgraph.opengl as gl
from pyqtgraph.opengl import GLViewWidget
from pyqtgraph import GraphicsLayoutWidget

from DIY.diy_progressbar import chartWidget as env_progress
# from chartAnalyse import chartWindow, AnalyseGlWidget
# from DIY.step import PddDialog,OarDialog
from win32api import GetSystemMetrics
import platform
# from myHelp import Helper
# helper = Helper()
import numpy as np
import json

BOOT_DIR= os.getcwd()
import configparser
config = configparser.ConfigParser()
config_file = BOOT_DIR +'/conf/config.ini'
config.read(config_file)

SKIN = config['base']['skin']
SIZE_X = int(config['base']['SIZE_X'])
SIZE_Y = int(config['base']['SIZE_Y'])
SIZE_Z = int(config['base']['SIZE_Z'])
# 本底测量阈值
ENV_THRESHOLD = int(config['base']['ENV_THRESHOLD'])
# 本底测量个数
ENV_COUNT = int(config['base']['ENV_COUNT'])
# 测量速度ms
MEASURE_SPEED = int(config['base']['MEASURE_SPEED'])
# 打开调试
#  DEBUG = bool(config['base']['DEBUG'])
if config['base']['DEBUG'] == 'False':
    DEBUG = False
else:
    DEBUG = True
DEBUG = True


VERSION = config['base']['VERSION']
#  VERSION = 'release'
# 串口监测周期ms
TIME_COM_CHECK = int(config['base']['TIME_COM_CHECK'])
# 串口接收周期ms
TIME_COM_RECV = int(config['base']['TIME_COM_RECV'])
# 串口查询周期ms
TIME_COM_FIND = int(config['base']['TIME_COM_FIND'])
# 1mm走位需要的脉冲数
PULSE_MM = int(config['base']['PULSE_MM'])
# 速度mm/s
SPEED_MM = int(config['base']['SPEED_MM'])

WATER_CMD = {
        '开高压':       ['AA', '0000', '00', '01', '', '00'],
        '关高压':       ['AA', '0000', '00', '02', '', '00'],
        '本底测量':     ['AA', '0000', '00', '72', '', '00'],
        '开始测量':     ['AA', '0000', '00', '71', '', '00'],
        '停止测量':     ['AA', '0000', '00', '73', '', '00'],
        '单次测量':     ['AA', '0000', '00', '74', '', '00'],
        '设置传输速度': ['AA', '0000', '00', '41', '', '00'],
        '设置走位速度': ['AA', '0000', '00', '07', '', '00'],
        '回程差x':      ['AA', '0000', '00', '21', '', '00'],
        '回程差y':      ['AA', '0000', '00', '22', '', '00'],
        '回程差z':      ['AA', '0000', '00', '23', '', '00'],
        '回程差':       ['AA', '0000', '00', '52', '', '00'],
        '电机走步x+':   ['AA', '0000', '00', '32', '', '00'],
        '电机走步x-':   ['AA', '0000', '00', '31', '', '00'],
        '电机走步y+':   ['AA', '0000', '00', '34', '', '00'],
        '电机走步y-':   ['AA', '0000', '00', '33', '', '00'],
        '电机走步z+':   ['AA', '0000', '00', '36', '', '00'],
        '电机走步z-':   ['AA', '0000', '00', '35', '', '00'],
        '电机走步':     ['AA', '0000', '00', '51', '', '00'],
        '连续测量':     ['AA', '0000', '00', '50', '', '00'],
        '数据写入':     ['AA', '0000', '00', '42', '', '00'],
        '数据读取':     ['AA', '0000', '00', '43', '', '00'],
        '复位坐标':     ['AA', '0000', '00', '44', '', '00'],
        '读取坐标':     ['AA', '0000', '00', '53', '', '00'],
        '移动停止':     ['AA', '0000', '00', '54', '', '00'],
        '任务坐标':     ['AA', '0000', '00', '5A', '', '00'],
        'x+':           ['AA', '0000', '00', '45', '', '00'],
        'x-':           ['AA', '0000', '00', '46', '', '00'],
        'y+':           ['AA', '0000', '00', '47', '', '00'],
        'y-':           ['AA', '0000', '00', '48', '', '00'],
        'z+':           ['AA', '0000', '00', '49', '', '00'],
        'z-':           ['AA', '0000', '00', '4A', '', '00'],
        'lowspeed':     ['AA', '0000', '00', '4B', '', '00'],
        'highspeed':    ['AA', '0000', '00', '4C', '', '00'],
    }
# 监督通道突变差阈值
slave_change_threshold = int(config['base']['slave_change_threshold'])

SAVE_PATH_TEMP = config['base']['SAVE_PATH_TEMP']
SAVE_PATH_DATA = config['base']['SAVE_PATH_DATA']
SAVE_PATH_CONF = config['base']['SAVE_PATH_CONF']

data_start = 0

# from data_test import data_pdd,oar_data


class drawWidget(QWidget):
    def __init__(self, parent=None):
        super(drawWidget, self).__init__(parent)
        self.setAutoFillBackground(True)
        #  palette = self.palette()
        #  palette.setColor(QPalette.Background, QColor(255, 255, 255))
        #  self.setPalette(palette)
        #  self.setWindowFlags(Qt.FramelessWindowHint)# 无窗体
        #  self.setAttribute(Qt.WA_TranslucentBackground)# 背景透明
        self.TextFont      = QFont("Arial", 10, QFont.Bold)
        self.stepTextFont      = QFont("Arial", 10, QFont.Bold)
        self.pen = [
            QPen(QColor(145,44,238)),
            QPen(QColor(132,112,255)),
            QPen(QColor(32,205,187)),
            QPen(QColor(255,0,255)),
            QPen(QColor(255,127,0)),
            QPen(QColor(255,215,0)),
        ]
        self.color = [
            QColor(145,44,238),
            QColor(132,112,255),
            QColor(32,205,187),
            QColor(255,0,255),
            QColor(255,127,0),
            QColor(255,215,0),
        ]
        self.step =[3,4,3]
        self.pos = [0,40,80,100]
        self.raySize = 10
        self.SSD = 100
        self.direction = 'x'
        # 扫描变量
        self.scanStep = 1
        self.scan_point_index = 0
        self.scanDirection = 'x'
        self.scanPoints = []

        self.pdd_oar_ray = 'pdd'
        if self.pdd_oar_ray == 'pdd':
            self.setFixedSize(600, 300)
        if self.pdd_oar_ray == 'oar':
            self.setFixedSize(600, 300)
        if self.pdd_oar_ray == 'ray':
            self.setFixedSize(600, 600)
        if self.pdd_oar_ray == 'scan':
            self.setFixedSize(600, 600)
        self.timer = QTimer()
        self.timer.timeout.connect(self.TimerMove)
        self.timer.start(50)
        self.updateScanRange(self.raySize,self.scanStep,'A->B')

    def paintEvent(self,e):
        painter = QPainter()
        painter.begin(self)
        painter.setRenderHints(QPainter.Antialiasing|QPainter.HighQualityAntialiasing)#设置反锯齿
        if self.pdd_oar_ray == 'oar':
            self.drawOarStep(painter)
        if self.pdd_oar_ray == 'pdd':
            self.drawPddStep(painter)
        if self.pdd_oar_ray == 'ray':
            self.drawRay(painter)
        if self.pdd_oar_ray == 'direction':
            self.drawDirection(painter)
        if self.pdd_oar_ray == 'scan':
            self.drawScan(painter)
        painter.end()

    def drawOarStep(self,painter):
        h = self.height()/2
        w = self.width()/2
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        # 系数
        d_x_1 = (9 / 10) * w
        d_y_1 = (7 / 10) * h
        step = self.step
        pos = self.pos
        if not len(pos)>1:
            return
        max_x = max(pos)
        # 移动坐标到左侧
        painter.translate(w,h)
        # 坐标转换比例系数
        perc = d_x_1/max(pos)
        painter.setFont(QFont("Arial", 8, QFont.Bold))
        #  painter.drawText(0, -h/2, d_x_1/1.8,-d_y_1/10, Qt.AlignCenter, '分步')
        # 放射源水平线
        # 画坐标轴
        #  painter.setFont(self.TextFont);
        painter.setPen(QPen(QColor(100, 0, 0), 2));
        painter.drawLine(-max_x*perc, d_y_1 , max_x*perc,d_y_1 ) #上
        for i in range(-int(max_x)-1,int(max_x)+1):
            if self.raySize<30:
                if i%10== 0:
                    # 画10位置的刻度线
                    painter.setPen(QPen(QColor(250, 0, 0), 2));
                    painter.drawLine(i*perc, d_y_1 , i*perc,d_y_1 -10)
                    painter.drawText(i*perc, d_y_1 , d_x_1/3, d_y_1/2, Qt.AlignLeft, '%s'%i)
            else:
                if i%20== 0:
                    painter.setPen(QPen(QColor(250, 0, 0), 2));
                    painter.drawLine(i*perc, d_y_1 , i*perc,d_y_1 -10)
                    painter.drawText(i*perc-10, d_y_1 , d_x_1/3, d_y_1/2, Qt.AlignLeft, '%s'%i)

        # 所有坐标位置
        pos_x = []
        for i in range(1,len(pos)):
            w = pos[i]-pos[i-1]
            end = 0
            h = d_y_1*(5-i)/5
            if i == 1:
                painter.drawLine(0, d_y_1, 0, -h)
                painter.drawText(pos[i-1]*perc,  -h*1.5, d_y_1/3, d_y_1/2, Qt.AlignLeft, '%.1f'%step[i-1])
            else:
                # 正
                painter.drawText(pos[i-1]*perc+d_y_1/4,  -h*1.5, d_y_1/3, d_y_1/2, Qt.AlignLeft, '%.1f'%step[i-1])
                # 负
                painter.drawText(-pos[i-1]*perc-d_y_1/2, -h*1.5, d_y_1/3, d_y_1/2, Qt.AlignLeft, '%.1f'%step[i-1])
            painter.setPen(self.pen[i-1])
            # 正 顶部线
            painter.drawLine(pos[i-1]*perc, -h, pos[i]*perc, -h)
            # 负 顶部线
            painter.drawLine(-pos[i-1]*perc, -h, -pos[i]*perc, -h)
            for j in range(1,int(w)+1):
                if j < w:
                    if j%step[i-1]== 0:
                        p = pos[i-1]+j
                        pos_x.append(p)
                        # 正
                        painter.drawLine(p*perc, d_y_1, p*perc, -h)
                        # 负
                        painter.drawLine(-p*perc, d_y_1, -p*perc, -h)
            p = pos[i-1]+j
            pos_x.append(p)
            painter.drawLine(p*perc, d_y_1, p*perc, -h)
            painter.drawLine(-p*perc, d_y_1, -p*perc, -h)

    def drawPddStep(self,painter):
        h = self.height()/2
        w = self.width()/2
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        # 系数
        d_x_1 = (9 / 10) * w
        d_y_1 = (7 / 10) * h

        step = self.step
        pos = self.pos
        if not len(pos)>1:
            return

        max_x = max(pos)
        # 移动坐标到左侧
        painter.translate(w-d_x_1,h)
        # 坐标转换比例系数
        perc = d_x_1/max(pos)*2
        painter.setFont(QFont("Arial", 8, QFont.Bold))
        # 放射源水平线
        # 画坐标轴
        #  painter.setFont(self.TextFont);
        painter.setPen(QPen(QColor(100, 0, 0), 2));
        painter.drawLine(0, d_y_1 , max_x*perc,d_y_1 ) #上
        for i in range(0,int(max_x)+1):
            if i%10== 0:
                # 画10位置的刻度线
                painter.setPen(QPen(QColor(250, 0, 0), 2));
                painter.drawLine(i*perc, d_y_1 , i*perc,d_y_1 -10)
                painter.drawText(i*perc, d_y_1 , d_x_1/3, d_y_1/2, Qt.AlignLeft, '%s'%i)

        # 所有坐标位置
        pos_x = []
        painter.setFont(self.stepTextFont);
        for i in range(1,len(pos)):
            w = pos[i]-pos[i-1]
            end = 0
            h = d_y_1*(5-i)/5
            if i == 1:
                painter.drawLine(0, d_y_1, 0, -h)
                painter.drawText(pos[i-1]*perc+d_y_1/2, -h*1.5, d_y_1/2, d_y_1/2, Qt.AlignLeft, '%.1f'%step[i-1])
            else:
                painter.drawText(pos[i-1]*perc+d_y_1/2, -h*1.5, d_y_1/2, d_y_1/2, Qt.AlignLeft, '%.1f'%step[i-1])
            painter.setPen(self.pen[i-1])
            painter.drawLine(pos[i-1]*perc, -h, pos[i]*perc, -h)
            for j in range(1,int(w)+1):
                if j < w:
                    if j%step[i-1]== 0:
                        p = pos[i-1]+j
                        pos_x.append(p)
                        # 正
                        painter.drawLine(p*perc, d_y_1, p*perc, -h)
                        # 负
                        #  painter.drawLine(-p*perc, axis_y, -p*perc, -h)
            p = pos[i-1]+j
            pos_x.append(p)
            painter.drawLine(p*perc, d_y_1, p*perc, -h)

    def drawRay(self,painter):
        h = self.height()/2
        w = self.width()/2
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        # 移动坐标系到中心
        painter.translate(w,h)
        # 系数
        d_x_1 = (9 / 10) * w
        d_y_1 = (9 / 10) * h
        painter.setFont(QFont("Arial", 12*d_x_1/1.8/w, QFont.Bold))
        # 画矩形 - 水箱
        painter.setBrush(QColor(125, 255, 255));
        painter.drawRect(-d_x_1, 0, 2*d_x_1, d_y_1);
        # 中心线
        painter.drawLine(0, -d_y_1, 0, d_y_1)
        d_x_2 = (5 / 10) * w * (self.raySize/60)
        d_y_2 = (5 / 10) * h
        # 放射源水平线
        # painter.drawLine(-d_x_2, 0, d_x_2,0)
        painter.drawLine(-d_x_2, -d_y_1 , d_x_2,-d_y_1 ) #上
        painter.drawText(-d_x_1/4, -d_y_1 , d_x_1/1.8,-d_y_1/10, Qt.AlignCenter, '射线照射')
        # 射野-红色
        painter.setPen(QPen(QColor(0, 0, 100), 5));
        painter.drawLine(-d_x_2, 0, d_x_2,0)
        painter.drawText(-d_x_2, d_y_2/3 , d_x_1/1.8,-d_y_1/10, Qt.AlignCenter, '射野:%.1fcm'%self.raySize)
        # 射野光线边缘线
        painter.setPen(QPen(QColor(200, 0, 0), 3));
        per = d_x_2/d_y_1
        d_x_3 = (d_y_1+d_y_1/2)*per
        d_y_3 = d_y_1/2
        painter.drawLine(0, -d_y_1, d_x_3 , d_y_3) #左斜线
        painter.drawLine(0, -d_y_1, -d_x_3 , d_y_3) #右斜线
        # SSD
        painter.setPen(QPen(QColor(0, 100, 0), 3));
        painter.drawLine(d_x_2, 0, d_x_2, -d_y_1)
        painter.drawText(d_x_2, -d_y_1/2, d_x_1/2,-d_y_1/10, Qt.AlignCenter, '源波距:%.1fcm'%self.SSD)

    def drawDirection(self,painter):
        h = self.height()/2
        w = self.width()/2
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        # 移动坐标系到中心
        painter.translate(w,h)
        # 系数
        d_x_1 = (9 / 10) * w
        d_y_1 = (9 / 10) * h
        painter.setFont(QFont("Arial", 12*d_x_1/1.8/w, QFont.Bold))
        # 画矩形 - 水箱
        painter.setBrush(QColor(125, 255, 255));
        painter.drawRect(-d_x_1, -d_y_1, 2*d_x_1, 2*d_y_1);
        # 画矩形 - 射野
        painter.setBrush(QColor(25, 5, 155));
        painter.drawRect(-d_x_1*2/3, -d_y_1*2/3, 2*d_x_1*2/3, 2*d_y_1*2/3);
        painter.drawText(-d_x_1/4, -d_y_1 , d_x_1/1.8,-d_y_1/10, Qt.AlignCenter, '方向顶视图')

        painter.setFont(QFont("Arial", 20, QFont.Bold))
        painter.drawText(d_x_1/2, 0 , d_x_1/1.8,-d_y_1/5, Qt.AlignCenter, 'B')
        painter.drawText(-d_x_1, 0 , d_x_1/1.8,-d_y_1/5, Qt.AlignCenter, 'A')
        painter.drawText(-d_x_1/3, -d_y_1*2/3 , d_x_1/1.8,-d_y_1/5, Qt.AlignCenter, 'T')
        painter.drawText(-d_x_1/3, d_y_1*2/2 , d_x_1/1.8,-d_y_1/5, Qt.AlignCenter, 'G')
        # 画xy - 射野
        #  painter.setBrush(QColor(25, 255, 255));
        painter.setPen(QPen(QColor(0, 200, 0), 3));
        # x线
        painter.drawLine(-d_x_1, 0, d_x_1, 0);
        # y线
        painter.drawLine(0, -d_y_1, 0, d_y_1);
        # x箭头
        painter.drawLine(w*9/10, 0, w*8/10, h/9);
        painter.drawLine(w*9/10, 0, w*8/10, -h/9);
        # y箭头
        painter.drawLine(0, -d_y_1, w/9, -h*8/10);
        painter.drawLine(0, -d_y_1, -w/9, -h*8/10);
        painter.setFont(QFont("Arial", 15, QFont.Bold))
        painter.drawText(d_x_1/1.5, 0,w/5,h/5, Qt.AlignCenter, 'x')
        painter.drawText(0,-d_y_1/1.1,w/5,h/5, Qt.AlignCenter, 'y')
        # 中心线
        painter.setPen(QPen(QColor(200, 0, 0), 3));
        if self.direction == 'AG->BT':
            painter.drawLine(-d_x_1*2/3, d_y_1*2/3, d_x_1*2/3, -d_y_1*2/3);
            painter.drawLine(0, 0, -d_x_1/8, 0);
            painter.drawLine(0, 0, 0, d_x_1/8);
        if self.direction == 'BT->AG':
            painter.drawLine(-d_x_1*2/3, d_y_1*2/3, d_x_1*2/3, -d_y_1*2/3);
            painter.drawLine(0, 0, d_x_1/8, 0);
            painter.drawLine(0, 0, 0, -d_x_1/8);
        if self.direction == 'BG->AT':
            painter.drawLine(-d_x_1*2/3, -d_y_1*2/3, d_x_1*2/3, d_y_1*2/3);
            painter.drawLine(0, 0, d_x_1/8, 0);
            painter.drawLine(0, 0, 0, d_x_1/8);
        if self.direction == 'AT->BG':
            painter.drawLine(-d_x_1*2/3, -d_y_1*2/3, d_x_1*2/3, d_y_1*2/3);
            painter.drawLine(0, 0, -d_x_1/8, 0);
            painter.drawLine(0, 0, 0, -d_x_1/8);
        if self.direction == 'A->B':
            painter.drawLine(-d_x_1*2/3, 0, d_x_1*2/3, 0);
            painter.drawLine(0, 0, -d_x_1/8, d_x_1/8);
            painter.drawLine(0, 0, -d_x_1/8, -d_x_1/8);
        if self.direction == 'B->A':
            painter.drawLine(d_x_1*2/3, 0, -d_x_1*2/3, 0);
            painter.drawLine(0, 0, d_x_1/8, d_x_1/8);
            painter.drawLine(0, 0, d_x_1/8, -d_x_1/8);
        if self.direction == 'G->T':
            painter.drawLine(0, d_y_1*2/3, 0 ,-d_y_1*2/3);
            painter.drawLine(0, 0, -d_y_1/8, d_y_1/8);
            painter.drawLine(0, 0, d_y_1/8, d_y_1/8);
        if self.direction == 'T->G':
            painter.drawLine(0, d_y_1*2/3, 0 ,-d_y_1*2/3);
            painter.drawLine(0, 0, -d_y_1/8, -d_y_1/8);
            painter.drawLine(0, 0, d_y_1/8, -d_y_1/8);

    def drawScan(self,painter):
        h = self.height()/2
        w = self.width()/2
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        # 移动坐标系到中心
        painter.translate(w,h)
        # 系数
        x = (8 / 10) * w
        y = (8 / 10) * h
        painter.setFont(QFont("Arial", 12, QFont.Bold))
        # painter.setBrush(QColor(125, 255, 255));
        painter.drawText(-x/2, -y, x/1, -y/4, Qt.AlignCenter, '扫描示意图')
        # 画矩形 - 水箱
        painter.setBrush(QColor(125, 255, 255));
        painter.drawRect(-x, -y, 2*x, 2*y);
        # painter.drawRect(0, 0, x, y);
        # 画矩形 - 射野
        size_x, size_y = x*2.5/3,y*2.5/3
        painter.setBrush(QColor(25, 5, 155));
        painter.drawRect(-size_x, -size_y, 2*size_x, 2*size_y);
        painter.setFont(QFont("Arial", 10, QFont.Bold))
        # penW = int(10-10*len(self.scanPoints)/1600)
        # if penW<2:
            # penW = 2
        if len(self.scanPoints_x)<50:
            painter.setPen(QPen(QColor(255, 5, 0), 5))
        else:
            painter.setPen(QPen(QColor(255, 5, 0), 2))
        # 移动坐标系到水箱左上角
        # painter.translate(-size_x,-size_y)
        # 画出所有点
        for i in range(0,len(self.scanPoints_x)):
            for j in range(0,len(self.scanPoints_x[i])):
                painter.drawPoint(self.scanPoints_x[i][j]*size_x*2/self.raySize/10,self.scanPoints_y[i][j]*size_y*2/self.raySize/10)
        # 画出运动当前点
        painter.setPen(QPen(QColor(5, 255, 0), 8));
        try:
            for i in range(0,len(self.scanPoints_x)):
                painter.drawPoint(self.scanPoints_x[i][self.scan_point_index]*size_x*2/self.raySize/10,self.scanPoints_y[i][self.scan_point_index]*size_y*2/self.raySize/10)
        except:
            pass

    def TimerMove(self):
        if self.pdd_oar_ray == 'scan':
            self.scan_point_index +=1
            if self.scan_point_index >= len(self.scanPoints_x):
                self.scan_point_index = 0
            self.update()

    def updatePddRoad(self,step=[2,5,10],pos=[0,10,30,300]):
        self.step = step
        self.pos = pos
        self.update()

    def updateOarRoad(self,step=[10,3,5],pos=[0,40,60,80]):
        self.step = step
        self.pos = pos
        self.update()

    def updateRaySize(self,size):
        self.raySize = size
        self.update()

    def updateScanRange(self,size,step,direction):
        self.raySize = size
        self.scanStep = step
        self.scanPoints = []
        s = self.raySize*10
        res = int(s) % int(self.scanStep)
        # 分割x,y
        x = np.arange(-s/2,s/2+1,step)
        y = np.arange(-s/2,s/2+1,step)
        if not res == 0:
            x = np.append(x, s/2)
            y = np.append(y, s/2)
        if direction == 'A->B':
            self.scanPoints_x, self.scanPoints_y = np.meshgrid(x, y)    # x-y 平面的网格
        if direction == 'G->T':
            self.scanPoints_y, self.scanPoints_x = np.meshgrid(x, y)    # x-y 平面的网格
        self.update()

    def updateSSD(self,ssd):
        self.SSD = ssd
        self.update()

    def updataAngle(self):
        self.currentValue=self.currentValue+9
        self.m_angle=self.m_angle+6
        # self.m_angle=m_angle+36
        if self.m_angle >360:
            self.m_angle = 0
        # self.currentValue=10
        if self.currentValue >self.maxValue:
            self.currentValue = 0
        self.update()

    def reject(self):
        QDialog.reject(self)

class PositionCanvasWidget(GLViewWidget):
    def __init__(self):
        super(PositionCanvasWidget, self).__init__()
        self.opts['distance'] = 60
        self.gx = gl.GLGridItem()
        self.gx.rotate(90, 0, 1, 0)
        self.gx.translate(-10, 0, 0)
        self.addItem(self.gx)
        self.gy = gl.GLGridItem()
        self.gy.rotate(90, 1, 0, 0)
        self.gy.translate(0, -10, 0)
        self.addItem(self.gy)
        self.gz = gl.GLGridItem()
        self.gz.translate(0, 0, -10)
        self.addItem(self.gz)
        # axis range ---> x,y,z
        self.x_min = -20
        self.x_max = 20
        self.y_min = -20
        self.y_max = 20
        self.z_min = -20
        self.z_max = 20
        # set real range
        self.x_range = SIZE_X
        self.y_range = SIZE_Y
        self.z_range = SIZE_Z
        # get transform scale
        self.x_scale = (self.x_max-self.x_min)/self.x_range
        self.y_scale = (self.y_max-self.y_min)/self.y_range
        self.z_scale = (self.z_max-self.z_min)/self.z_range
        # draw direction A->B
        self.vLine = gl.GLLinePlotItem(pos=np.array([[self.x_min/2,0,self.z_min/2],[self.x_max/2,0,self.z_min/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
        self.addItem(self.vLine)
        # draw direction G->T
        self.hLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_max/2,self.z_min/2]]), color=pg.glColor(250,0,255), width=1, antialias=True)
        self.addItem(self.hLine)
        # draw direction Z
        self.zLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_min/2,self.z_max/2]]), color=pg.glColor(250,0,55), width=1, antialias=True)
        self.addItem(self.zLine)
        # pos line
        self.xline = gl.GLLinePlotItem(pos=np.array([[0,0,0],[0,self.y_min/2,0]]), color=pg.glColor(0,0,225), width=1, antialias=True)
        self.addItem(self.xline)
        self.yline = gl.GLLinePlotItem(pos=np.array([[0,0,0],[self.x_min/2,0,0]]), color=pg.glColor(0,0,225), width=1, antialias=True)
        self.addItem(self.yline)
        self.zline = gl.GLLinePlotItem(pos=np.array([[0,0,0],[0,0,self.z_min/2]]), color=pg.glColor(0,0,225), width=1, antialias=True)
        self.addItem(self.zline)
        # move scatter
        self.sp_pos = gl.GLScatterPlotItem(pos=np.array([[0,0,0]]), size=0.5, color=(1.0, 0, 0.0, 0.8), pxMode=False)
        self.addItem(self.sp_pos)
        self.sp_road = gl.GLScatterPlotItem(pos=np.array([[0,0,0]]), size=0.3, color=(0, 1.0, 0.0, 0.8), pxMode=False)
        self.addItem(self.sp_road)
        self.points = []

        self.updatePos(50,50,100)

    def paintGL(self, *args, **kwds):
        GLViewWidget.paintGL(self, *args, **kwds)
        self.qglColor(Qt.white)
        for i in range(self.x_min,self.x_max+1):
            if i%5 == 0:
                # x axis
                self.renderText(i/2, self.y_max/2+2, self.z_min/2, str(int(i/self.x_scale)))
                # y axis
                self.renderText(self.x_max/2+2, i/2, self.z_min/2, str(int(i/self.y_scale)))
                # z axis
                self.renderText(self.x_min/2, self.y_max/2+1, i/2, str(int(self.z_range/2-i/self.z_scale)))
        self.renderText(0, 0, self.z_max/2+5, '移动示意图')
        self.qglColor(Qt.blue)
        self.renderText(self.x_min/2, self.y_max/2, 12, 'd(mm)')
        self.renderText(0, self.y_max/2+5, self.z_min/2, 'x(mm)')
        self.renderText(self.x_max/2+5, 0, self.z_min/2, 'y(mm)')
        # draw direction text
        self.qglColor(Qt.green)
        self.renderText(self.x_min/2, 0, self.z_min/2, 'A')
        self.renderText(self.x_max/2, 0, self.z_min/2, 'B')
        self.renderText(0, self.y_min/2, self.z_min/2, 'G')
        self.renderText(0, self.y_max/2, self.z_min/2, 'T')

    def updatePos(self, x, y, z):
        x = x*self.x_scale/2
        y = y*self.y_scale/2
        z = (self.z_range/2-z)*self.z_scale/2
        pts = [[x,y,z]]
        self.sp_pos.setData(pos = np.array(pts))
        self.xline.setData(pos = np.array([[x,y,z],[x,self.y_min/2,z]]))
        self.yline.setData(pos=np.array([[x,y,z],[self.x_min/2,y,z]]))
        self.zline.setData(pos=np.array([[x,y,z],[x,y,self.z_min/2]]))
        # self.xline.setData(pos = np.array([[x,y,z],[x,self.y_min/2,z]]))
        # self.xline = gl.GLLinePlotItem(pos=np.array([[0,0,0],[0,self.y_min/2,0]]), color=pg.glColor(0,200,55), width=1, antialias=True)
        # self.xline.setData()
        # self.xline.setData()

    def showRoad(self, road):
        pts = [[r[0]*self.x_scale/2, r[1]*self.y_scale/2,(self.z_range/2-r[2])*self.z_scale/2] for r in road]
        self.sp_road.setData(pos = np.array(pts))

from AddPddDialog import PddDialog
from AddOarDialog import OarDialog
from AddScanDialog import ScanDialog, ScanResultWidget
from DeviceSelectDialog import DeviceInputDlg
from RayGraphWidget import RayCanvasWidget


class GraphWidget(GraphicsLayoutWidget):
    def __init__(self):
        super(GraphWidget, self).__init__()
        # 右上角显示
        self.label = pg.LabelItem(justify='right')
        self.addItem(self.label,      0,1,1,1)
        # 曲线添加
        self.plot = pg.PlotItem()
        self.plot = self.addPlot(1,1,colspan=2)
        self.plot.setYRange(0,100)

        self.data = np.random.normal(size=10)
        self.curve_master_data= [100,100]
        self.curve_slave_data= [0,0]
        self.curve_data_x = [0,300]
        # 曲线设置
        self.plot.setAutoVisible(y=True)
        self.plot.setTitle('通道数据实时曲线图')
        self.plot.setLabel('left', "相对剂量(%)", units='')
        self.plot.setLabel('bottom', "距离(mm)", units='')
        self.plot.addLegend()
        # 主测通道和监测通道
        self.curve_master = self.plot.plot(self.curve_data_x,self.curve_master_data,name='主测通道',pen=pg.mkPen('g', width=2))
        self.curve_slave = self.plot.plot(self.curve_data_x,self.curve_slave_data,name='监测通道',pen=pg.mkPen('r', width=2))
        # 网格显示
        self.plot.showGrid(x = True, y = True, alpha = 0.7)
        # 鼠标坐标显示文本
        self.text_pos = pg.TextItem("(0,0)", anchor=(0.5, -1.0),color='k')
        self.plot.addItem(self.text_pos)
        self.text_pos.setPos(0,0)
        #鼠标十字移动
        self.vLine = pg.InfiniteLine(pen=pg.mkPen('b', width=1),angle=90, movable=False)
        self.hLine = pg.InfiniteLine(pen=pg.mkPen('b', width=1),angle=0, movable=False)
        self.plot.addItem(self.vLine, ignoreBounds=True)
        self.plot.addItem(self.hLine, ignoreBounds=True)
        #鼠标移动绑定
        self.vb = self.plot.vb
        self.proxy = pg.SignalProxy(self.plot.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
        self.plot.autoRange()

    def find_nearest(self,array,value):
        idx = (np.abs(array-value)).argmin()
        return array[idx]

    def mouseMoved(self, evt):
        tx = np.array(self.curve_data_x)
        pos = evt[0]
        if self.plot.sceneBoundingRect().contains(pos):
            mousePoint = self.vb.mapSceneToView(pos)
            self.vLine.setPos(mousePoint.x())
            self.hLine.setPos(mousePoint.y())
            self.setCursor(Qt.BlankCursor)
            self.text_pos.setText("(%0.1f,%0.1f)"%(mousePoint.x(),mousePoint.y()))
            self.text_pos.setPos(mousePoint.x(),mousePoint.y())
            # self.label.setText("<span style='font-size: 12pt'>x=%0.1f,  <span style='color: red'>y=%0.1f</span>" % (mousePoint.x(), mousePoint.y()))
            # index = int(mousePoint.x())
            # try:
                # n = self.find_nearest(tx,index)
                # index = np.where(tx==n)[0][0]
                # self.label.setText("<span style='font-size: 12pt;color: blue'>通道实时数据:  </span>\
                                    # <span style='font-size: 12pt'>x=\t{:20},  \
                                # <span style='color: red'>y1=\t{:28}</span> ,\
                                # <span style='color: green'>y2=\t{:32}</span>"\
                                # .format('%0.1f'%mousePoint.x(), '%0.1f'%self.curve_master_data[index],'%0.1f'%self.curve_slave_data[index]))
                # self.vLine.setPos(mousePoint.x())
                # self.hLine.setPos(mousePoint.y())
            # except:
                # pass

    def drawLine(self,x,y):
        self.curve_master.setData(x=self.curve_data_x,y=self.curve_master_data)
        self.curve_slave.setData(x=self.curve_data_x,y=self.curve_slave_data)

    def draw_two(self,x,master,slave):
        self.plot.autoRange()
        if max(master) == 0 or max(slave) == 0:
            master = [m*100/(max(master)+0.000001) for m in master]
            slave = [m*100/(max(slave)+0.000001) for m in slave]
        else:
            master = [m*100/max(master) for m in master]
            slave = [m*100/max(slave) for m in slave]
        self.curve_master.setData(x=x,y=master)
        self.curve_slave.setData(x=x,y=slave)
        # self.plot.setXRange(0,300)
        # self.plot.setYRange(0,120)

    def clear_data(self):
        self.curve_data_x = []
        self.curve_master_data= []
        self.curve_slave_data= []
        self.curve_master.setData(x=self.curve_data_x,y=self.curve_master_data)
        self.curve_slave.setData(x=self.curve_data_x,y=self.curve_slave_data)

    def drawLineAppend(self):
        self.curve_master.setData(self.curve_master_data)
        self.curve_slave.setData(self.curve_slave_data)

    def tunnelZero(self):
        self.curve_data_x = []
        self.curve_slave_data=[]
        self.curve_master_data=[]
        self.drawLine()

# from opengl_obj import glWidget
class TaskTabView(QTableView):
    signalClick = pyqtSignal(dict)
    def __init__(self, parent=None,pddDlg=None,oarDlg=None,scanDlg=None):
        '''表格初始化'''
        super(TaskTabView, self).__init__(parent)
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['详情','进度']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.resizeRowsToContents()
        self.resizeColumnsToContents()
        #  self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.setModel(self.model)
        self.setColumnWidth(0,50)
        #下面代码让表格100填满窗口
        self.horizontalHeader().setStretchLastSection(True)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 设置可以多选
        self.setSelectionMode(QAbstractItemView.ExtendedSelection);
        self.setSelectionBehavior(QAbstractItemView.SelectRows);
        # 任务和进度列表
        self.task_progress_list = []
        self.task_list = []
        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)
        # 点击
        self.clicked.connect(self.Clicked)

        self.select_row = -1
        # 开始启动前加载最新配置
        # self.loadRecentTask()
        self.pddDlg = pddDlg
        self.oarDlg = oarDlg
        self.scanDlg = scanDlg

    def right_menu(self):
        self.menu = QMenu()
        deleteAction = QAction("&删除选中任务")
        deleteAction.triggered.connect(self.deleteSelected)
        showInfoAction = QAction("&显示/修改信息")
        showInfoAction.triggered.connect(self.showInfo)
        clearAction = QAction("&清空任务")
        clearAction.triggered.connect(self.clearTask)
        self.menu.addAction(deleteAction)
        self.menu.addAction(showInfoAction)
        self.menu.addAction(clearAction)
        # exportExcleAction = menu.addAction("&导出表格到excel")
        self.menu.exec(QCursor.pos())

    def addTask(self,t):
        self.task_list.append(t)
        rowNum = self.model.rowCount() # 总行数
        progress = QProgressBar()
        progress.setRange(0,len(t['road']))
        progress.setValue(0)
        self.task_progress_list.append(progress)
        inf = '%s/%s/%s/%s/%s/%s*%s/%s'%(t['type'] , t['rayType'], t['power'], t['ssd'], t['deepth'], t['raySizeX'], t['raySizeY'],t['direction'])
        self.model.setItem(rowNum, 0, QStandardItem(str(inf)))
        self.model.setItem(rowNum, 1, QStandardItem(str('')))
        self.setIndexWidget(self.model.index(rowNum, 1), progress)

    def addTask_bk(self,t):
        self.task_list.append(t)
        rowNum = self.model.rowCount() # 总行数
        progress = QProgressBar()
        progress.setRange(0,len(t['road']))
        progress.setValue(0)
        self.task_progress_list.append(progress)
        self.model.setItem(rowNum, 0, QStandardItem(str(rowNum)))
        self.model.setItem(rowNum, 1, QStandardItem(str('')))
        self.setIndexWidget(self.model.index(rowNum, 1), progress)
        self.model.setItem(rowNum, 2, QStandardItem(str(t['type'])))

    def deleteSelected(self):
        '''删除选中行'''
        try:
            if not QMessageBox.warning(self,'警告','确认要删除么？',QMessageBox.Yes|QMessageBox.No) == 65536:
                self.model.removeRow(self.select_row)
                del self.task_list[self.select_row]
                del self.task_progress_list[self.select_row]
        except:
            QMessageBox.warning(self,'错误','没有选中要删除的行!',QMessageBox.Yes)

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Delete:
            self.deleteSelected()

    def clearTask(self):
        self.model.clear()
        self.model = QStandardItemModel(0, 0)
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        self.task_list = []
        self.task_progress_list = []

    def showInfo(self):
        '''显示详细信息'''
        if self.select_row < 0 :
            QMessageBox.warning(self,'错误','没有选中要显示的行!',QMessageBox.Yes)
            return
        c = self.task_list[self.select_row]
        if c['type'] == 'PDD':
            self.pddDlg.load_config(c)
            self.pddDlg.setWindowTitle('PDD任务修改')
            if self.pddDlg.exec() == QDialog.Accepted:
                conf = self.pddDlg.conf
                self.task_list[self.select_row] = conf
                inf = '%s/%s/%s/%s/%s/%s*%s/%s'%(
                    conf['type'], conf['rayType'], conf['power'], conf['ssd'], conf['deepth'], conf['raySizeX'], conf['raySizeY'],conf['direction'])
                self.model.setItem(self.select_row, 0, QStandardItem(str(inf)))
        if c['type'] == 'OAR':
            self.oarDlg.load_config(c)
            self.oarDlg.setWindowTitle('OAR任务修改')
            if self.oarDlg.exec() == QDialog.Accepted:
                conf = self.oarDlg.conf
                self.task_list[self.select_row] = conf
                inf = '%s/%s/%s/%s/%s/%s*%s/%s'%(
                    conf['type'], conf['rayType'], conf['power'], conf['ssd'], conf['deepth'], conf['raySizeX'], conf['raySizeY'],conf['direction'])
                self.model.setItem(self.select_row, 0, QStandardItem(str(inf)))
        if c['type'] == 'SCAN':
            self.scanDlg.load_config(c)
            self.scanDlg.setWindowTitle('SCAN任务修改')
            if self.scanDlg.exec() == QDialog.Accepted:
                conf = self.scanDlg.conf
                self.task_list[self.select_row] = conf
                inf = '%s/%s/%s/%s/%s/%s*%s/%s'%(
                    conf['type'], conf['rayType'], conf['power'], conf['ssd'], conf['deepth'], conf['raySizeX'], conf['raySizeY'],conf['direction'])
                self.model.setItem(self.select_row, 0, QStandardItem(str(inf)))

    def saveTask(self):
        '''保存任务配置'''
        if not len(self.task_list)>0:
            QMessageBox.information(self, "消息", "请添加任务后操作!", QMessageBox.Yes)
            return
        fileName, ok = QFileDialog.getSaveFileName(self,
                                    "配置文件保存",
                                    os.getcwd() + "/conf",
                                    "Task Files (*.task)")
        # print(fileName,ok)
        # timetest = time.strftime("%Y%m%d%H%M%S", time.localtime())
        # name = QInputDialog.getText(self, "保存数据","任务名称:",QLineEdit.Normal, "%s_配置1"%timetest)
        if fileName:
            try:
                with open(fileName,'w') as f:
                    for t in self.task_list:
                        f.write(json.dumps(t)+'\n')
                    QMessageBox.information(self, "消息", "配置保存成功", QMessageBox.Yes)
                    with open(config_file,'w') as c:
                        config.set('base', 'recent_task_conf_path', fileName)
                        config.write(c)
            except:
                QMessageBox.information(self, "消息", "配置保存失败：配置文件名称错误!", QMessageBox.Yes)

    def loadTaskRecent(self):
        '''加载最近任务配置'''
        self.clearTask()
        filename = self.sender().text()
        try:
            name = r'%s'%filename.replace('&','')
            with open(name,'r') as f:
                for line in f.readlines():
                    t = json.loads(line.replace('\n',''))
                    self.addTask(t)
        except:
            QMessageBox.information(self, "消息", "配置加载失败:配置文件被占用或不存在!", QMessageBox.Yes | QMessageBox.No)

    def loadTask(self):
        '''加载任务配置'''
        fdlg = QFileDialog(self)
        fdlg.setWindowTitle(r'打开文件')
        fdlg.setDirectory(os.getcwd()+'/conf')
        fdlg.setNameFilter(r'TASK Files(*.task)')
        fdlg.setFileMode(QFileDialog.ExistingFiles)
        if fdlg.exec() == QDialog.Accepted:
            files = fdlg.selectedFiles()
            self.clearTask()
            for name in files:
                try:
                    with open(name,'r') as f:
                        for line in f.readlines():
                            t = json.loads(line.replace('\n',''))
                            self.addTask(t)
                except:
                    QMessageBox.information(self, "消息", "配置加载失败:配置文件被占用或不存在!", QMessageBox.Yes | QMessageBox.No)

    def uploadProgress(self,cnt,value):
        '''刷新进度显示'''
        self.task_progress_list[cnt].setValue(value)

    def clearProgresssAll(self):
        '''清除进度显示'''
        for p in self.task_progress_list:
            p.setValue(p.minimum())

    def clearProgressFromSelect(self):
        "从选择位置处往下清除进度显示"
        for i in range(self.select_row,len(self.task_progress_list)):
            self.task_progress_list[i].setValue(self.task_progress_list[i].minimum())

    def clearProgress(self,pos):
        "从选择位置处往下清除进度显示"
        for i in range(pos,len(self.task_progress_list)):
            self.task_progress_list[i].setValue(self.task_progress_list[i].minimum())


    def Clicked(self,index):
        self.select_row = index.row()
        self.signalClick.emit(self.task_list[self.select_row])

    def showCurrentTask(self, row):
        self.signalClick.emit(self.task_list[row])

    def mouseDoubleClickEvent(self, event):
        self.showInfo()

class DataTabView(QTableView):
    def __init__(self, parent=None):
        '''表格初始化'''
        super(DataTabView, self).__init__(parent)
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['x(mm)','y(mm)','z(mm)','主测通道','监测通道','修正','归一化']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        #下面代码让表格100填满窗口
        self.horizontalHeader().setStretchLastSection(True)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.isClearChooseLine_Flag = False
        #  self.setMaximumHeight(250)

        self.clear_data()
        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)

    def right_menu(self):
        self.menu = QMenu()
        exportAction = QAction("&导出excel",triggered=self.exportToExcel)
        self.menu.addAction(exportAction)
        self.menu.exec(QCursor.pos())

    def exportToExcel(self):
        f = QFileDialog.getSaveFileName(self,"导出Excel",'%s/data'%os.getcwd(),'Excel Files(*.xls)')
        if f[0]:
            try:
                filename = f[0]
                wb = xlwt.Workbook()
                ws = wb.add_sheet('sheet1')#sheetname
                data = []
                data.append(self.HeaderList)
                row = self.model.rowCount()
                for r in range(0,row):
                    data.append([
                        float(self.model.data(self.model.index(r,0))),
                        float(self.model.data(self.model.index(r,1))),
                        float(self.model.data(self.model.index(r,2))),
                        float(self.model.data(self.model.index(r,3))),
                        float(self.model.data(self.model.index(r,4))),
                        float(self.model.data(self.model.index(r,5))),
                        float(self.model.data(self.model.index(r,6))),
                    ])
                for i in range(0,len(data)):
                    for j in range(0,len(data[i])):
                        ws.write(i, j, data[i][j])
                wb.save(filename)
                QMessageBox.warning(self,'提示','导出成功!\r\n%s'%filename,QMessageBox.Yes)
            except:
                QMessageBox.warning(self,'警告','文件被占用，无法导出!',QMessageBox.Yes)

    def clear_data(self):
        self.model.clear()
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['x(mm)','y(mm)','z(mm)','主测通道','监测通道','修正','归一化']
        # self.HeaderList = ['时间','深度','主测通道','监测通道','修正','归一化']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)

    def add_data(self,x='',y='',z='',t1='',t2=''):
        rowNum = self.model.rowCount()  # 总行数
        # t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # self.model.setItem(rowNum, 0, QStandardItem(str(t)))
        self.model.setItem(rowNum, 0, QStandardItem(str(x)))
        self.model.setItem(rowNum, 1, QStandardItem(str(y)))
        self.model.setItem(rowNum, 2, QStandardItem(str(z)))
        self.model.setItem(rowNum, 3, QStandardItem(str(t1)))
        self.model.setItem(rowNum, 4, QStandardItem(str(t2)))

    def get_standard(self,x,ave):
        import math
        n = len(x)
        s = 0
        for i in range(0,n):
            s = s+pow((int(x[i])-ave),2)
        s = math.sqrt(1/(n-1)*s)
        return s

    def get_data(self):
        rowNum = self.model.rowCount()  # 总行数
        x = [self.model.data(self.model.index(i, 1)) for i in range(0,rowNum)]
        line1 = [self.model.data(self.model.index(i, 4)) for i in range(0,rowNum)]
        line2 = [self.model.data(self.model.index(i, 5)) for i in range(0,rowNum)]
        return (x,line1,line2)

    def get_all_data(self):
        rowNum = self.model.rowCount()  # 总行数
        colNum = self.model.columnCount()  # 总行数
        data = []
        for j in range(0,colNum):
            col = [self.model.data(self.model.index(i, j)) for i in range(0,rowNum)]
            data.append(col)
        return data

from ui.main import Ui_MainWindow
from chartAnalyse import chartAnalyseForm
from ui import images
class MainWindow(QMainWindow, Ui_MainWindow):
    '''三维水箱主程序'''
    signalOpengl = pyqtSignal(float,float,float)
    signalOpenglRoad = pyqtSignal(list)
    signalEnv = pyqtSignal(int)
    signalTunnel = pyqtSignal(list,list,list)
    signalProgress = pyqtSignal(int,int)
    signalProgressClear = pyqtSignal(int)
    #  移动距离
    err_x = 0
    err_y = 0
    err_z = 0
    #  真实坐标
    real_x = 0
    real_y = 0
    real_z = 0
    #  前一刻坐标
    pre_x = 0
    pre_y = 0
    pre_z = 0
    pulse_x = 0
    pulse_y = 0
    pulse_z = 0
    #  本底测量标志
    env_measure_flag = False
    #  移动标志
    move_flag = False
    task_flag = False
    taskmove_flag = False
    task_cnt = 0
    task_current = None
    task = None
    # 意外停止标志
    stop_flag = False
    # 任务第一个点移动显示标志
    task_move_first_flag = True
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        import PyQt5_stylesheets
        # if SKIN == 'style_Dark':
        # self.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
        # if SKIN == 'style_Default':

        self.setStyleSheet('None')
            # pass
        self.setupUi(self)
        #  self.dockWidget_config.setWindowTitle('配置')
        #  self.dockWidget_opengl.setWindowTitle('移动图')
        w = QApplication.desktop().screenGeometry().width()
        h = QApplication.desktop().screenGeometry().height()
        self.setMinimumSize(w*0.98,h*0.9)
        # 3d显示控件
        self.chart = RayCanvasWidget()
        self.chart.setMinimumHeight(h/2)
        self.verticalLayout_opengl.addWidget(self.chart)
        # 曲线显示窗口
        self.graph = GraphWidget()
        self.graphScan = ScanResultWidget()
        self.dataTab= DataTabView()
        # # 加速器设备添加窗口
        self.deviceInputDlg = DeviceInputDlg()
        self.verticalLayout_chart.addWidget(self.graph)
        self.verticalLayout_chart.addWidget(self.graphScan)
        self.verticalLayout_data_table.addWidget(self.dataTab)
        # PDD  OAR
        self.pddDlg = PddDialog()
        self.oarDlg = OarDialog()
        self.scanDlg= ScanDialog()
        self.chartAnalyse = chartAnalyseForm()
        self.verticalLayout_chartAnalyse.addWidget(self.chartAnalyse)
        # 表格控件
        self.tabView = TaskTabView(pddDlg=self.pddDlg, oarDlg=self.oarDlg,scanDlg=self.scanDlg)
        # self.taskListWidget = TaskListWidget(pddDlg=self.pddDlg, oarDlg=self.oarDlg)
        self.verticalLayout_task_table.addWidget(self.tabView)
        self.tabView.setMaximumWidth(w/3)
        # self.verticalLayout_task_table.addWidget(self.taskListWidget)
        # 按钮响应
        self.btn_pddTask.clicked.connect(self.addPddTask)
        self.btn_oarTask.clicked.connect(self.addOarTask)
        self.btn_scanTask.clicked.connect(self.addScanTask)
        # self.btn_saveTask.clicked.connect(self.tabView.saveTask)
        # self.btn_loadTask.clicked.connect(self.tabView.loadTask)
        # self.btn_clearTask.clicked.connect(self.tabView.clearTask)
        # self.menubar
        # # 曲线处理模块
        # # self.chartAnalyseWindow = chartWindow(skin=SKIN)
        # # Ui初始化
        # self.ui_init()
        self.createActions()
        self.createMenus()
        # self.menu_init()
        # 串口监测定时器
        self.serial_init()
        # 坐标3d显示信号
        self.signalOpengl.connect(self.updateSpinPos)
        # # self.signalOpenglRoad.connect(self.openglDock.chart.showRoad)
        # 本底测试信号
        self.env_bar = env_progress()
        self.signalEnv.connect(self.env_bar.update_env)
        # 曲线显示信号绑定
        self.signalTunnel.connect(self.graph.draw_two)
        self.signalProgress.connect(self.tabView.uploadProgress)
        # self.signalProgress.connect(self.taskListWidget.uploadProgress)
        self.tabView.signalClick.connect(self.chart.load_config)

        # 按钮信号绑定
        self.pushButton_back_zero.clicked.connect(self.cmd_backZero)
        self.pushButton_reset_axis.clicked.connect(self.cmd_ResetAxis)
        # self.pushButton_set_speed.clicked.connect(self.cmd_SetSpeed)
        self.pushButton_move.clicked.connect(lambda:self.motorMoveAxis_position(self.doubleSpinBox_x.value(),self.doubleSpinBox_y.value(),self.doubleSpinBox_z.value()))
        self.horizontalSlider_x.setRange(-300*100,300*100)
        self.horizontalSlider_y.setRange(-300*100,300*100)
        self.horizontalSlider_z.setRange(-400*100,400*100)
        self.horizontalSlider_x.setPageStep(100)
        self.horizontalSlider_y.setPageStep(100)
        self.horizontalSlider_z.setPageStep(100)
        self.horizontalSlider_x.setSingleStep(100)
        self.horizontalSlider_y.setSingleStep(100)
        self.horizontalSlider_z.setSingleStep(100)
        self.doubleSpinBox_x.setRange(-300,300)
        self.doubleSpinBox_y.setRange(-300,300)
        self.doubleSpinBox_z.setRange(-400,400)
        self.horizontalSlider_x.valueChanged.connect(self.sliderChanged)
        self.horizontalSlider_y.valueChanged.connect(self.sliderChanged)
        self.horizontalSlider_z.valueChanged.connect(self.sliderChanged)
        self.doubleSpinBox_x.valueChanged.connect(self.spinChanged)
        self.doubleSpinBox_y.valueChanged.connect(self.spinChanged)
        self.doubleSpinBox_z.valueChanged.connect(self.spinChanged)
        self.spinChanged()
        self.pushButton_runTask.clicked.connect(self.taskRunInit)
        self.pushButton_stopTask.clicked.connect(self.cmd_MoveStop)
        self.pushButton_continueTask.clicked.connect(self.continueMove)
        self.setWindowIcon(QIcon(':icons/images_rc/app.ico'))
        self.deviceInputDlg.setWindowIcon(QIcon(':icons/images_rc/app.ico'))
        self.pddDlg.setWindowIcon(QIcon(':icons/images_rc/app.ico'))
        self.oarDlg.setWindowIcon(QIcon(':icons/images_rc/app.ico'))
        self.scanDlg.setWindowIcon(QIcon(':icons/images_rc/app.ico'))

    def createActions(self):
        '''菜单设置'''
        self.exitAct = QAction(QIcon(':icons/images_rc/close.png'),"&退出", self, shortcut="Ctrl+Q",
                statusTip="关闭程序", triggered=self.close)

        self.printAct = QAction(QIcon(':icons/images_rc/printer.png'),"&打印", self, shortcut="Ctrl+P",
                triggered=self.chartAnalyse.on_printAction1_triggered)
        self.printAct.setEnabled(False)

        self.printPreviewAct = QAction(QIcon(':icons/images_rc/view.png'),"&打印预览",
                triggered=self.chartAnalyse.on_printAction2_triggered)
        self.printPreviewAct.setEnabled(False)

        self.loadTaskAct = QAction(QIcon(':icons/images_rc/open.png'),"&加载配置", triggered=self.tabView.loadTask)

        self.saveTaskAct = QAction(QIcon(':icons/images_rc/save.png'),"&保存配置", triggered=self.tabView.saveTask)


        def files_by_time_reversed(path, reverse=True):
            return sorted(glob.glob(os.path.join(path, '*')), key=lambda x: time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime(x))), reverse=reverse)
        task_files = files_by_time_reversed(os.getcwd()+'\\conf',reverse=False)
        self.taskFileActions = []
        for s in task_files:
            if s.endswith('.task'):
                Action = QAction(QIcon(':icons/images_rc/file.png'),"&%s"%s,self,triggered=self.tabView.loadTaskRecent)
                self.taskFileActions.append(Action)
        self.addPddTaskAct = QAction(QIcon(':icons/images_rc/pdd.png'),"&添加PDD任务", triggered=self.addPddTask)

        self.addOarTaskAct = QAction(QIcon(':icons/images_rc/oar.png'),"&添加OAR任务", triggered=self.addOarTask)

        self.addScanTaskAct = QAction(QIcon(':icons/images_rc/scan.png'),"&添加扫描任务",self, triggered=self.addScanTask)

        self.chartAnalyseAct = QAction(QIcon(':icons/images_rc/chartAnalyse.png'), '&曲线分析', self,
                                         triggered=self.chartAnalyseShow)
        self.chartAnalyseAct.setCheckable(True)

        # 操作菜单action
        self.envAct_M = QAction(QIcon(':icons/images_rc/environment.png'), '&本底测量', self,
                                triggered=self.env_start)
        self.startMeasureAct_M = QAction("&测量开始", triggered=self.startMeasure)

        self.stopMeasureAct_M= QAction("&测量停止", triggered=self.stopMeasure)

        self.setSpeedAct_M = QAction(QIcon(':icons/images_rc/speed.png'), '&设置速度', self,
                                     triggered=self.cmd_SetSpeed)

        self.backZeroAct_M= QAction(QIcon(':icons/images_rc/backzero.png'), '&回原点', self,
                                    triggered=self.cmd_backZero)

        self.zeroAct_M= QAction(QIcon(':icons/images_rc/clear.png'), '&复位坐标', self,
                                triggered=self.cmd_ResetAxis)

        # 串口
        self.comOpenAct = QAction(QIcon(':icons/images_rc/com.png'), '&打开串口', self,
                                  shortcut='Ctrl+O',triggered=self.OpenCom)
        self.comSearchAct = QAction(QIcon(':icons/images_rc/search.png'), '&查询串口', self,
                                  shortcut='Ctrl+F',triggered=self.FindCom)
        ## 串口状态
        self.comboBox_port= QComboBox()
        self.qta_com_status= QLabel()
        self.qta_com_status.setStyleSheet('color: red;')
        self.qta_com_status.setFont(qta.font('fa', 32))
        self.qta_com_status.setText(unichr(0xf111))
        # 光机选择
        self.deviceAct= QAction(QIcon(':icons/images_rc/devices.png'), '&光机选择', self,
                                triggered=self.deviceInputDlg.exec)
        # self.addPddTaskAct = QAction(QIcon(':icons/images_rc/devices.png'),'&PDD任务',self,triggered=self.addPddTask)
        # self.addOarTaskAct = QAction(QIcon(':icons/images_rc/devices.png'),'&OAR任务',self,triggered=self.addOarTask)
        # self.addScanTaskAct = QAction(QIcon(':icons/images_rc/devices.png'),'&SCAN任务',self,triggered=self.addScanTaskAct)
        self.startTaskAct = QAction(QIcon(':icons/images_rc/start.png'),'&开始执行',self,triggered=self.startMove)
        self.stopTaskAct= QAction(QIcon(':icons/images_rc/stop.png'),'&紧急停止',self,triggered=self.pauseMove)
        self.continueMoveAct= QAction(QIcon(':icons/images_rc/pause.png'),'&继续执行',self,triggered=self.continueMove)
        self.selectMoveAct= QAction(QIcon(':icons/images_rc/devices.png'),'&选择处执行',self,triggered=self.selectMove)
        # 走位
        self.chartAnalyseAct= QAction(QIcon(':icons/images_rc/chartAnalyse.png'), '&曲线分析', self,
                            triggered=self.chartAnalyseShow)
        self.chartTMRAct= QAction(QIcon(':icons/images_rc/tmr.png'), '&导出TMR', self,
                            triggered=self.chartAnalyse.showTMR)
        # 皮肤
        self.skinAct= QAction(QIcon(':icons/images_rc/skin.png'), '&换肤', self,
                            triggered=self.skinChanged)
        self.skin_num = 1

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&文件")
        self.taskFileMenu = self.fileMenu.addMenu(QIcon(':icons/images_rc/open.png'),"&最近配置")
        self.taskFileMenu.addActions(self.taskFileActions)
        self.fileMenu.addAction(self.loadTaskAct)
        self.fileMenu.addAction(self.saveTaskAct)
        self.fileMenu.addAction(self.printAct)
        self.fileMenu.addAction(self.printPreviewAct)

        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)

        self.viewMenu = self.menuBar().addMenu("&视图")
        self.viewMenu.addAction(self.addPddTaskAct)
        self.viewMenu.addAction(self.addOarTaskAct)
        self.viewMenu.addAction(self.addScanTaskAct)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.chartAnalyseAct)
        self.viewMenu.addAction(self.chartTMRAct)

        self.operateMenu = self.menuBar().addMenu("&操作")
        self.operateMenu.addAction(self.envAct_M)
        self.operateMenu.addAction(self.startMeasureAct_M)
        self.operateMenu.addAction(self.stopMeasureAct_M)
        self.operateMenu.addAction(self.setSpeedAct_M)
        self.operateMenu.addAction(self.backZeroAct_M)
        self.operateMenu.addAction(self.zeroAct_M)

        self.toolbar = self.addToolBar('工具栏')
        # self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.toolbar.addAction(self.deviceAct)
        self.toolbar.addWidget(QLabel('--->'))
        self.toolbar.addAction(self.addPddTaskAct)
        self.toolbar.addAction(self.addOarTaskAct)
        self.toolbar.addAction(self.addScanTaskAct)
        self.toolbar.addWidget(QLabel('--->'))
        self.toolbar.addWidget(self.qta_com_status)
        self.toolbar.addWidget(self.comboBox_port)
        self.toolbar.addAction(self.comSearchAct)
        self.toolbar.addAction(self.comOpenAct)
        self.toolbar.addWidget(QLabel('--->'))
        self.toolbar.addAction(self.startTaskAct)
        self.toolbar.addAction(self.stopTaskAct)
        self.toolbar.addAction(self.continueMoveAct)
        self.toolbar.addAction(self.selectMoveAct)
        self.startTaskAct.setEnabled(False)
        self.stopTaskAct.setEnabled(False)
        self.continueMoveAct.setEnabled(False)
        self.selectMoveAct.setEnabled(False)
        self.toolbar.addWidget(QLabel('--->'))
        self.toolbar.addAction(self.chartAnalyseAct)
        self.toolbar.addAction(self.chartTMRAct)
        self.toolbar.addAction(self.skinAct)

    def skinChanged(self):
        self.skin_num += 1
        if self.skin_num == 1:
            self.setStyleSheet('None')
            self.pddDlg.setStyleSheet('None')
            self.oarDlg.setStyleSheet('None')
            self.scanDlg.setStyleSheet('None')
            self.deviceInputDlg.setStyleSheet('None')
        elif self.skin_num == 2:
            self.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
            self.pddDlg.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
            self.oarDlg.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
            self.scanDlg.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
            self.deviceInputDlg.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
            self.skin_num = 0

    def updateSpinPos(self, x, y, z):
        self.doubleSpinBox_x.setValue(float(x))
        self.doubleSpinBox_y.setValue(float(y))
        self.doubleSpinBox_z.setValue(float(z))
        self.chart.updatePos(x,y,z)

    def addPddTask(self):
        '''添加pdd任务'''
        self.pddDlg.setWindowTitle('PDD任务添加')
        if self.pddDlg.exec() == QDialog.Accepted:
            conf = self.pddDlg.conf
            self.tabView.addTask(conf)

    def addOarTask(self):
        '''添加oar任务'''
        self.oarDlg.setWindowTitle('OAR任务添加')
        if self.oarDlg.exec() == QDialog.Accepted:
            conf = self.oarDlg.conf
            self.tabView.addTask(conf)

    def addScanTask(self):
        '''添加扫描任务'''
        self.scanDlg.setWindowTitle('SCAN任务添加')
        if self.scanDlg.exec() == QDialog.Accepted:
            conf = self.scanDlg.conf
            self.tabView.addTask(conf)

    def sliderChanged(self):
        self.doubleSpinBox_x.setValue(self.horizontalSlider_x.value()/100)
        self.doubleSpinBox_y.setValue(self.horizontalSlider_y.value()/100)
        self.doubleSpinBox_z.setValue(self.horizontalSlider_z.value()/100)

    def spinChanged(self):
        self.horizontalSlider_x.setValue(self.doubleSpinBox_x.value()*100)
        self.horizontalSlider_y.setValue(self.doubleSpinBox_y.value()*100)
        self.horizontalSlider_z.setValue(self.doubleSpinBox_z.value()*100)

    def chartAnalyseShow(self):
        if self.stackedWidget.currentIndex() == 0:
            self.stackedWidget.setCurrentIndex(1)
            # self.chartAnalyse.TaskTree.get_file_list_db_sql()
            self.printAct.setEnabled(True)
            self.printPreviewAct.setEnabled(True)
            self.chartAnalyseAct.setChecked(True)
        else:
            self.printAct.setEnabled(False)
            self.printPreviewAct.setEnabled(False)
            self.chartAnalyseAct.setChecked(False)
            self.stackedWidget.setCurrentIndex(0)
        return
        try:
            win32api.ShellExecute(0, 'open', '%s/chartAnalyse.exe'%os.getcwd(), '','',1)
        except:
            QMessageBox.warning( self, '错误', '曲线分析程序未安装', QMessageBox.Yes)

    def serial_init(self):
        '''初始化串口'''
        self.serial = serial.Serial()
        self.serial.timeout = 0.5# make sure that the alive event can be checked from time to time
        self.thread = None
        self.serial_alive = False
        self.serial.port = None
        self.serial.baudrate = '115200'
        self.serial.bytesize = 8
        self.serial.parity   = 'N'
        self.serial.stopbits = 1
        self.serial.dtr      = True
        self.serial.rts      = True
        self.recv = ''
        # 串口查询定时器
        # self.timerFindCom= QTimer()
        # self.timerFindCom.timeout.connect(self.FindCom)
        # self.timerFindCom.start(TIME_COM_FIND)
        self.portList = []
        # 串口监测定时器
        self.timerCheckCom= QTimer()
        self.timerCheckCom.timeout.connect(self.CheckCom)
        # self.timerCheckCom.start(TIME_COM_CHECK)
        # 串口接收定时器
        self.timerRecvCom= QTimer()
        self.timerRecvCom.timeout.connect(self.RecvCom)

    def FindCom(self):
        '''串口搜索'''
        self.comboBox_port.clear()
        if platform.system() == 'Windows':
            port_list = list(serial.tools.list_ports.comports())
            p = [port[0]+':'+port[1] for port in port_list]
        if platform.system() == 'Linux':
            port_list = list(serial.tools.list_ports.comports())
            p = [port[0] for port in port_list]
        # port_list = list(serial.tools.list_ports.comports())
        # p = [port[0]+':'+port[1] for port in port_list]
        # if not len(self.portList) == len(p):
            # self.comboBox_port.clear()
        self.comboBox_port.addItems(p)

    def CheckCom(self):
        '''检查串口是否正常运行'''
        if not self.serial_alive:
            self.serial.close()
            self.qta_com_status.setStyleSheet('color: red;')
            self.comOpenAct.setEnabled(True)
            self.timerRecvCom.stop()
            self.timerCheckCom.stop()
            self.comboBox_port.clear()
            self.taskRunFinish()
            self.startTaskAct.setEnabled(False)
            self.stopTaskAct.setEnabled(False)
            self.continueMoveAct.setEnabled(False)
            self.selectMoveAct.setEnabled(False)
            QMessageBox.information( self, '串口错误', '串口通信中断', QMessageBox.Yes)

    def OpenCom(self):
        '''打开串口'''
        if not self.deviceInputDlg.select_ID > 0:
            self.deviceInputDlg.exec()
            # QMessageBox.warning(self,'警告','加速器未选择，无法执行任务',QMessageBox.Yes)
            return
        self.task = self.tabView.task_list
        self.task_cnt = 0
        if not self.task:
            QMessageBox.warning(self,'警告','请添加任务',QMessageBox.Yes)
            return
        if self.serial_alive:
            self.serial_alive = False
            return
        port = self.comboBox_port.currentText()
        baudrate= '115200'
        if port and baudrate:
            self.serial.port = port
            self.serial.baudrate= baudrate
            try:
                self.serial.open()
            except serial.SerialException as e:
                QMessageBox.information( self, '串口打开错误', '错误原因：\n %s'%e, QMessageBox.Yes)
            else:
                self.timerCheckCom.start(TIME_COM_CHECK)
                self.timerRecvCom.start(TIME_COM_RECV)
                self.serial_alive = True
                self.comOpenAct.setEnabled(False)
                self.qta_com_status.setStyleSheet('color: green;')
                self.cmd_read_axis()
                self.taskRunInit()
                self.startTaskAct.setEnabled(True)
                self.stopTaskAct.setEnabled(True)
                self.continueMoveAct.setEnabled(True)
                self.selectMoveAct.setEnabled(True)
                if VERSION == 'release':
                    self.env_start()
                # 开启串口时要读取坐标
                # QMessageBox.information( self, '串口通信', '串口打开', QMessageBox.Yes)
        else:
            QMessageBox.warning( self, '错误', '未查询到串口', QMessageBox.Yes)

    def RecvCom(self):
        """ 串口接收 """
        # while self.serial_alive.isSet():
        try:
            n = self.serial.inWaiting()
            if n:
                b = self.serial.read(n)
                #将byte转换为十六进制字符串
                data = str(binascii.b2a_hex(b).decode('utf-8'))
                self.recv += data.upper()
                # if DEBUG:
                    # print('接收命令：',' '.join([self.recv[i*2:i*2+2] for i in range(0,int(len(self.recv)/2))]))
                try:
                    self.cmd_deal()
                except Exception as e:
                    print(e)
        except:
            self.serial_alive = False

    def WriteCom(self, cmd):
        '''串口写入,十六进制格式字符串'''
        if self.serial_alive:
            if self.serial.isOpen():
                data = binascii.unhexlify(cmd)
                if DEBUG:
                    print('发送命令：',' '.join([cmd[i*2:i*2+2] for i in range(0,int(len(cmd)/2))]))
                self.serial.write(data)
        else:
            QMessageBox.information( self, '通信提示', '通信异常,请检查通信接口', QMessageBox.Yes)

    def cmd_send(self,cmd_list):
        '''发送命令'''
        if DEBUG:
            print((cmd_list))
        cmd = ''.join(cmd_list)
        cmd.upper()
        cmd_start = cmd_list[0]
        cmd_len = hex(int(len(cmd)/2)).replace('0x','').zfill(4).upper()
        cmd_list[1] = cmd_len
        if len(cmd_len)==4:
            hex_len = int(cmd_len[:2],16) + int(cmd_len[-2:],16)
            cmd_sum = (hex(int(cmd_start,16) + int(cmd_len[:2],16) + int(cmd_len[-2:],16))).upper()[-2:]
        if len(cmd_len)==2:
            hex_len = int(cmd_len,16)
            cmd_sum = (hex(int(cmd_start,16) + int(cmd_len,16))).upper()[-2:]
        # print(cmd_sum)
        cmd_list[2] = cmd_sum
        s = 0
        s = int(cmd_list[0],16)+ hex_len + int(cmd_list[2],16)+ int(cmd_list[3],16)
        for i in range(0,len(cmd_list[4])):
            if i%2 == 0:
                s = s + int(cmd_list[4][i:i+2],16)
        s = hex(s).upper()[-2:]
        cmd_list[-1] = s
        send = ''.join(cmd_list)
        self.WriteCom(send)

    def cmd_deal_bk(self):
        '''串口处理命令，监测校验和是否正确'''
        cmd = self.recv
        cmd.upper()
        str_start = cmd.find("AA")
        startwith = cmd.startswith('AA')
        if not startwith:
            self.recv=''
            return
        if str_start>=0:
            cmd = cmd[str_start:]
            theory_len = int(cmd[2:4],16)
            real_len = len(cmd)/2
            if real_len>theory_len:
                self.recv = ''
                return
            if real_len == theory_len:
                cmd     = cmd[0:theory_len*2]
                cmd_start = cmd[0:2]
                cmd_len = cmd[2:4]
                cmd_sum = cmd[4:6]
                if cmd_sum == (hex(int(cmd_start,16) + int(cmd_len,16))).upper()[-2:]:
                    cmd_cmd = cmd[6:8]
                    cmd_data = cmd[8:-2]
                    cmd_endsum = cmd[-2:]
                    s = 0
                    for i in range(0,len(cmd)-2):
                        if i%2 == 0:
                            s = s + int(cmd[i:i+2],16)
                    s = hex(s).upper()[-2:]
                    if s == cmd_endsum:
                        if DEBUG:
                            print(cmd_cmd,cmd_data)
                        try:
                            self.cmd_type(cmd_cmd,cmd_data)
                        except Exception as e:
                            print(e)
                    else:
                        if DEBUG:
                            print('校验错误！！！！！！！！')
                            print('正确：',s, '错误:',cmd_endsum)
                self.recv = ''

    def cmd_deal(self):
        '''串口处理命令，监测校验和是否正确'''
        self.recv = self.recv
        start = self.recv.find("AA")
        startwith = self.recv.startswith('AA')
        def find_last(string,s):
            last_position=-1
            while True:
                position=string.find(s,last_position+1)
                if position==-1:
                    return last_position
                last_position=position
        start_num = len(re.compile('.*?(AA).*?').findall(self.recv))
        if start_num>1:
            print('*'*500)
        # if len(re.compile('.*?(AA).*?').findall(self.recv))>=3:
            # print(find_last(self.recv,'AA'))
            # self.recv=self.recv[find_last(self.recv,'AA'):]
            # print(self.recv)
        if self.recv.startswith('AA'):
            for i in re.compile('.*?(AA).*?').findall(self.recv):
                theory_len = int(self.recv[2:4],16)
                real_len = len(self.recv)/2
                if theory_len <= real_len:
                    cmd = self.recv[start:theory_len*2]
                    self.recv = self.recv[theory_len*2:]
                    # print('截取后',self.recv)
                    cmd_start = cmd[0:2]
                    cmd_len = cmd[2:4]
                    cmd_sum = cmd[4:6]
                    if cmd_sum == (hex(int(cmd_start,16) + int(cmd_len,16))).upper()[-2:]:
                        cmd_cmd = cmd[6:8]
                        cmd_data = cmd[8:-2]
                        cmd_endsum = cmd[-2:]
                        s = 0
                        for i in range(0,len(cmd)-2):
                            if i%2 == 0:
                                s = s + int(cmd[i:i+2],16)
                        s = hex(s).upper()[-2:]
                        if s == cmd_endsum:
                            if DEBUG:
                                print(cmd_cmd,cmd_data)
                            try:
                                self.cmd_type(cmd_cmd,cmd_data)
                            except Exception as e:
                                print(e)
                        else:
                            if DEBUG:
                                self.recv = ''
                                print('校验错误！！！！！！！！')
                                print('正确：',s, '错误:',cmd_endsum)
                else:
                    return
        else:
            self.recv = self.recv[self.recv.find('AA'):]

    def cmd_type(self,cmd_cmd,cmd_data):
        if cmd_cmd == '07':
            QMessageBox.information( self, '提示', '设置速度成功！', QMessageBox.Yes)
        if cmd_cmd == '72':# 本底测量
            t = int(cmd_data,16)*MEASURE_SPEED/1000
            t1 = float('%0.1f'%(100-t*100/30))
            self.signalEnv.emit(t1)
            if DEBUG:
                print('本底测量剩余时间:%s'%t)
            if t==0:
                self.env_measure_flag = True
                self.env_write_ok = True
                self.env_step += 1
        if cmd_cmd == '71': # 开始测量
            self.env_measure(cmd_data)
        if cmd_cmd == '74':
            self.stepMeasure(cmd_data)
        if cmd_cmd == '73': # 停止测量
            if DEBUG:
                print('停止测量')
        if cmd_cmd == '41':
            QMessageBox.information( self, '提示', '设置传输速度成功', QMessageBox.Yes)
            if DEBUG:
                print(self.clr.yellow('设置传输速度成功'))
        if cmd_data == '21':
            self.cmd_ReturnTripError(_type='y')
            if DEBUG:
                print(self.clr.yellow('回程差x'))
        if cmd_data == '22':
            self.cmd_ReturnTripError(_type='z')
            if DEBUG:
                print(self.clr.yellow('回程差y'))
        if cmd_data == '23':
            if DEBUG:
                print(self.clr.yellow('回程差z'))
                print(('回程差设置完成'))
        if cmd_data == '31':
            self.recv_ElectricMove_X()
            if DEBUG:
                print(self.clr.yellow('电机走步x+'))
        if cmd_data == '32':
            self.recv_ElectricMove_X()
            if DEBUG:
                print(self.clr.yellow('电机走步x-'))
        if cmd_data == '33':
            self.recv_Move_Y()
        if cmd_data == '34':
            self.recv_Move_Y()
        if cmd_data == '35':
            self.recv_Move_Z()
        if cmd_cmd == '51':
            '单步移动完成'
            self.stepMove(cmd_data)# 单步走位
        if cmd_cmd == '50':
            self.continueMeasure(cmd_data)# 连续走位
        if cmd_cmd == '5A':
            # helper.save_pdd_oar_data(SAVE_PATH_TEMP,self.task_current,self.pddoarList)
            # 数据库保存
            self.deviceInputDlg.save_data(self.task_current,self.pddoarList)
            print(self.task_cnt)
            print(len(self.task))
            if self.task_cnt>=len(self.task)-1:
                self.doneMove()
            else:
                self.taskRunThread.nextRun()
                self.task_move_first_flag = True
                self.progress_value = 0
                self.pddoarList = []
        if cmd_cmd == '42':# flash写入
            self.signalMsg.emit('写入信息成功')
        if cmd_cmd == '43':# flash读取
            sx = int(cmd_data[2:8],16)/100000
            sy = int(cmd_data[8:14],16)/100000
            sz = int(cmd_data[14:20],16)/100000
            rx = int(cmd_data[20:22],16)/10
            ry = int(cmd_data[22:24],16)/10
            rz = int(cmd_data[24:26],16)/10
            inf = '读出信息:\r\n\r\n电机x系数:\t%s\r\n电机y系数:\t%s\r\n电机z系数:\t%s\r\n\r\n回程差x:\t%s\r\n回程差y:\t%s\r\n回程差z:\t%s\r\n'%(sx,sy,sz,rx,ry,rz)
            self.signalMsg.emit(inf)
        if cmd_cmd == '44':# 复位坐标
            self.real_x = 0
            self.real_y = 0
            self.real_z = 0
            self.pre_x= 0
            self.pre_y= 0
            self.pre_z= 0
            self.signalOpengl.emit(0,0,0)
            QMessageBox.information( self, '提示', '坐标复位成功', QMessageBox.Yes)
        if cmd_cmd == '53':# 读取坐标
            self.real_x,self.real_y,self.real_z=self.get_xyz(cmd_data)
            self.signalOpengl.emit(self.real_x,self.real_y,self.real_z)
        if cmd_cmd == '54':# 紧急停止
            self.stop_flag = True
            if len(self.pddoarList)>1:
                del self.pddoarList[-1]
                del self.pddoarList[-1]
            else:
                self.pddoarList = []
            self.task_flag = False
            # self.real_x,self.real_y,self.real_z=self.get_xyz(cmd_data)
            data = cmd_data[2:]
            x = self.HexToNeg(data[2:10])
            y = self.HexToNeg(data[12:20])
            z = self.HexToNeg(data[22:30])
            self.real_x = float('%.5f'%(x/PULSE_MM))
            self.real_y = float('%.5f'%(y/PULSE_MM))
            self.real_z = float('%.5f'%(z/PULSE_MM))
            self.signalOpengl.emit(self.real_x,self.real_y,self.real_z)

    def get_xyz(self,cmd_data):
        '''处理数据包中包含的xyz坐标'''
        data = cmd_data[2:]
        if data[2:4] == 'FF':#计算通道x
            x = int(data[2:10],16)-int('FFFFFFFF',16)-1
        else:
            x = int(data[2:10],16)
        if data[12:14] == 'FF':#计算通道y
            y = int(data[12:20],16)-int('FFFFFFFF',16)-1
        else:
            y = int(data[12:20],16)
        if data[22:24] == 'FF':#计算通道z
            z = int(data[22:30],16)-int('FFFFFFFF',16)-1
        else:
            z = int(data[22:30],16)
        return x/PULSE_MM , y/PULSE_MM , z/PULSE_MM

    def cmd_read_axis(self):
        '''读取当前坐标坐标'''
        cmd = WATER_CMD['读取坐标']
        self.cmd_send(cmd)

    def startMeasure(self):
        '开始测量'
        self.dataTab.clear_data()
        self.measureList = []
        self.measureX = 0
        self.env_measure_flag = False
        self.cmd_send(WATER_CMD['开始测量'])

    def stopMeasure(self):
        '停止测量'
        self.cmd_send(WATER_CMD['停止测量'])

    def env_start(self):
        '''开始本底测量'''
        self.env_step = 0 # 本底测量步骤
        self.env_write_ok = True
        self.env_measure_t1 = []
        self.env_measure_t2 = []
        self.env_measure_flag = False
        self.env_measure_cnt= 0
        self.timer_env = QTimer()
        self.timer_env.timeout.connect(self.env_timer)
        self.timer_env.start(1000)
        self.dataTab.clear_data()
        self.env_bar.exec()

    def env_timer(self):
        if self.env_write_ok:
            if self.env_step == 0: # 第1步打开本底测量
                self.cmd_send(WATER_CMD['本底测量'])
                self.env_write_ok = False
            if self.env_step == 1: # 第2步打开测量
                self.cmd_send(WATER_CMD['开始测量'])
                self.env_write_ok = False
            if self.env_step == 2: # 第3步关闭测量
                self.cmd_send(WATER_CMD['停止测量'])
                self.env_write_ok = False
            if self.env_step == 3:
                self.timer_env.stop()

    def env_measure(self,data):
        '''调试测量数据'''
        t1 = 0
        t2 = 0
        if data[:2] == 'FF':
            t1 = int(data[:8],16)-int('FFFFFFFF',16)-1
        else:
            t1 = int(data[:8],16)
        if data[-8:-6] == 'FF':
            t2 = int(data[-8:],16)-int('FFFFFFFF',16)-1
        else:
            t2 = int(data[-8:],16)
        if self.env_measure_flag:
            self.dataTab.add_data(x=self.real_x,y=self.real_y,z=self.real_z,t1=t1,t2=t2)
            self.env_measure_cnt += 1
            self.env_measure_t1.append(abs(t1))
            self.env_measure_t2.append(abs(t2))
            cnt = ENV_COUNT
            self.signalEnv.emit(float('%0.1f'%(self.env_measure_cnt*100/int(cnt))))
            if self.env_measure_cnt>cnt:
                self.env_measure_flag = False
                self.env_measure_cnt = 0
                self.env_write_ok = True
                self.env_step += 1
                ave_t1 = sum(self.env_measure_t1)/len(self.env_measure_t1)
                ave_t2 = sum(self.env_measure_t2)/len(self.env_measure_t2)
                self.env_bar.close()
                if ave_t1<ENV_THRESHOLD and ave_t2<ENV_THRESHOLD:
                    # self.qta_env_status.setStyleSheet('color:green;')
                    QMessageBox.information( self, '漏射线测量', '测量合格', QMessageBox.Yes)
                else:
                    # self.qta_env_status.setStyleSheet('color:red;')
                    QMessageBox.information( self, '漏射线测量', '测量不合格', QMessageBox.Yes)
                self.cmd_send(WATER_CMD['停止测量'])
        else:
            self.dataTab.add_data(x=self.real_x,y=self.real_y,z=self.real_z,t1=t1,t2=t2)
            self.measureX += 1
            self.measureList.append([self.measureX,t1,t2])
            data = self.measureList
            self.signalTunnel.emit([d[0] for d in data],[d[1] for d in data],[d[2] for d in data],)

    def cmd_SetSpeed(self):
        '''速度设置'''
        cmd = WATER_CMD['设置走位速度']
        speed = hex(int(abs(72000000/400/SPEED_MM))).replace('0x','').zfill(8).upper()
        cmd[4] = speed
        self.cmd_send(cmd)

    def cmd_backZero_bk(self):
        '''回到原点'''
        # 获取坐标
        # self.cmd_ReadAxis()
        # 回原点
        self.back_zero_flag = True
        self.measure_flag = False
        self.task_move_first_flag = False
        self.motorMoveAxis_position(0,0,0)

    def cmd_ResetAxis(self):
        '''复位坐标系'''
        cmd = WATER_CMD['复位坐标']
        cmd[4] = ''
        self.cmd_send(cmd)

    def cmd_MoveStop(self):
        '''紧急停止'''
        cmd = WATER_CMD['移动停止']
        cmd[4] = ''
        self.cmd_send(cmd)
        # self.back_zero_flag = False
        # 开启移动标志
        self.move_flag = False
        self.stop_flag = True
        # self.road_cnt= 0
        self.task_flag = False

    def motorMoveAxis_position(self,x,y,z):
        self.err_x = float(x) - self.real_x
        self.err_y = float(y) - self.real_y
        self.err_z = float(z) - self.real_z
        # self.move_flag = True
        if self.err_x < 0:
            cmd_x = ('32')
        else:
            cmd_x = ('31')
        if self.err_y < 0:
            cmd_y = ('34')
        else:
            cmd_y = ('33')
        if self.err_z < 0:
            cmd_z = ('36')
        else:
            cmd_z = ('35')
        if DEBUG:
            print(('电机走步差值 x:%s y:%s z:%s'%(self.err_x,self.err_y,self.err_z)))
            print('电机正在移动到坐标:')
            print(('(%s,%s,%s)'%(x,y,z)))
        pulse_x = PULSE_MM
        pulse_y = PULSE_MM
        pulse_z = PULSE_MM
        cmd = WATER_CMD['电机走步']
        data_x = hex(int(abs(self.err_x*PULSE_MM))).replace('0x','').zfill(8).upper()
        data_y = hex(int(abs(self.err_y*PULSE_MM))).replace('0x','').zfill(8).upper()
        data_z = hex(int(abs(self.err_z*PULSE_MM))).replace('0x','').zfill(8).upper()
        cmd[4] = cmd_x+data_x+cmd_y+data_y+cmd_z+data_z
        self.cmd_send(cmd)

    def motorMoveAxis_continue(self,x,y,z,step_x,step_y,step_z):
        self.err_x = float(x) - self.real_x
        self.err_y = float(y) - self.real_y
        self.err_z = float(z) - self.real_z
        # self.move_flag = True
        if self.err_x < 0:
            cmd_x = ('32')
        else:
            cmd_x = ('31')
        if self.err_y < 0:
            cmd_y = ('34')
        else:
            cmd_y = ('33')
        if self.err_z < 0:
            cmd_z = ('36')
        else:
            cmd_z = ('35')
        if DEBUG:
            print(('电机走步差值 x:%s y:%s z:%s'%(self.err_x,self.err_y,self.err_z)))
            print('电机正在移动到坐标:')
            print(('(%s,%s,%s)'%(x,y,z)))
        cmd = WATER_CMD['连续测量']
        data_x = hex(int(abs(self.err_x*PULSE_MM))).replace('0x','').zfill(8).upper()
        data_y = hex(int(abs(self.err_y*PULSE_MM))).replace('0x','').zfill(8).upper()
        data_z = hex(int(abs(self.err_z*PULSE_MM))).replace('0x','').zfill(8).upper()
        step_pulse_x = hex(int(abs(step_x*PULSE_MM))).replace('0x','').zfill(8).upper()
        step_pulse_y = hex(int(abs(step_y*PULSE_MM))).replace('0x','').zfill(8).upper()
        step_pulse_z = hex(int(abs(step_z*PULSE_MM))).replace('0x','').zfill(8).upper()
        cmd[4] = cmd_x+data_x+cmd_y+data_y+cmd_z+data_z+\
                '3A'+step_pulse_x+'3B'+step_pulse_y+'3C'+step_pulse_z
        self.cmd_send(cmd)

    def get_road_axis(self, road):
        '''获取任务路线所有坐标'''
        road = []

    def db_save_data(self,device_id,task,data):
        data_list = [Data(x=d[1],y=d[2],z=d[3],tm=d[4],ts=d[5]) for d in data ]
        cond = Condition(
            rayType      = str(task['rayType']),
            type         = str(task['type']),
            ssd          = str(task['ssd']),
            power        = str(task['power']),
            direction    = str(task['direction']),
            deepth       = str(task['deepth']),
            raySizeX     = str(task['raySizeX']),
            raySizeY     = str(task['raySizeY']),
            datas        = data_list,)
        dev = session.query(Device).filter(Device.id==device_id).first()
        if dev:
            dev.conditions.append(cond)
            session.commit()

    def graphChange(self):
        "图表切换"
        if self.task_current['type'] == 'SCAN':
            self.graph.setVisible(False)
            self.graphScan.setVisible(True)
        else:
            self.graph.setVisible(True)
            self.graphScan.setVisible(False)
        self.scanPoint_x = np.array([])
        self.scanPoint_y = np.array([])
        self.scanPoint_z = np.array([])

    def taskRunInit(self):
        "开始移动控制线程"
        self.msg_queue = Queue()
        # 创建移动控制线程
        self.moveControlThread = Thread(target=self.MoveControlThread, args=(self.msg_queue,))
        self.moveControlThread_done = False
        self.moveControlThread.setDaemon(True)
        self.moveControlThread.start()
        # 创建任务执行流程线程
        self.taskRunThread= self.TaskRunThread(self.msg_queue)
        self.taskRunThread.start()
        self.msg_queue.join()
        self.signalProgressClear.connect(self.tabView.clearProgress)

    def taskRunFinish(self):
        "关闭移动控制线程"
        self.taskRunThread.done = True
        self.moveControlThread_done = True

    def startMove(self):
        self.task = self.tabView.task_list
        self.taskRunThread.firstRun()

    def selectMove(self):
        self.task = self.tabView.task_list
        self.taskRunThread.selectRun()

    def continueMove(self):
        self.task = self.tabView.task_list
        self.taskRunThread.continueRun()

    def pauseMove(self):
        self.task = self.tabView.task_list
        self.taskRunThread.pauseRun()

    def doneMove(self):
        "任务执行完成"
        self.task_flag = False
        self.move_flag = False
        self.measure_flag = False
        self.task_cnt = 0
        # 设置移动到第一个点标记
        self.task_move_first_flag = False
        self.progress_value = 0
        # 清除线程中的步骤
        self.taskRunThread.step = 0
        QMessageBox.information(self, "消息", "所有任务执行完成!", QMessageBox.Yes)

    def MoveControlThread(self, in_q):
        while not self.moveControlThread_done:
            # 获取消息队列中的消息
            msg = in_q.get()
            print(">>>接收到处理指令:",msg)
            # 处理消息
            if msg == "CONTINUE": # 执行当前任务
                self.task_cnt = self.taskRunThread.step
                self.task_current = self.task[self.taskRunThread.step]
                self.cmd_RunTask(self.task_current)
            if msg == "FIRST": # 从起始位置开始移动
                self.taskRunThread.step = 0
                self.taskRunThread.moveToFirstPos()
                self.signalProgressClear.emit(0)
            if msg == "SELECT": # 从指定位置开始移动
                self.taskRunThread.step = self.tabView.select_row
                self.taskRunThread.moveToFirstPos()
                self.signalProgressClear.emit(self.task_cnt)
            if msg == "PAUSE": # 暂停
                if self.progress_value >= 2:
                    self.progress_value -= 2
                else:
                    self.progress_value = 0
                self.cmd_MoveStop()
            if msg == "NEXT": # 下一任务
                self.taskRunThread.moveToFirstPos()
            if msg == "MOVE_FIRST": # 移动到第一个点位置
                self.task_current = self.task[self.taskRunThread.step]
                self.task_cnt = self.taskRunThread.step
                t = self.task_current
                self.motorMoveAxis_position(t['road'][0][0],t['road'][0][1],t['road'][0][2])
                self.task_move_first_flag = True
                self.progress_value = 0
                self.measure_flag = True
                self.pddoarList = []
                self.tabView.showCurrentTask(self.task_cnt)
            if msg == "MOVE_ZERO":
                self.motorMoveAxis_position(0,0,0)

            # 指示完成
            in_q.task_done()

    class TaskRunThread(Thread):
        def __init__(self,msg_queue):
            Thread.__init__(self)
            self.setDaemon(True)
            # 线程开关
            self.done = False
            # 开始运行一次标志
            self.start_run = False
            # 执行进度
            self.step = 0
            # 暂停标志
            self.isPause = False
            # 继续标志
            self.continue_run = False
            # 下一个标志
            self.next_run = False
            # 第一个点
            self.isFirst = False
            # 定位执行标志
            self.select_run= False
            self.first_run = False
            # 消息推送堆栈
            self.msg_queue = msg_queue

        def run(self):
            while not self.done:
                time.sleep(0.1)
                if self.start_run: # 执行一次
                    self.start_run = False
                    if self.isPause: # 暂停
                        self.isPause = False
                        self.msg_queue.put("PAUSE")
                    else:
                        # if self.step < len(self.task):
                        if self.continue_run: # 继续执行
                            self.continue_run = False
                            self.msg_queue.put("CONTINUE")
                        if self.select_run: # 选择位置处执行任务
                            self.select_run = False
                            self.msg_queue.put("SELECT")
                        if self.first_run: # 第一个任务开始执行
                            self.first_run = False
                            self.msg_queue.put("FIRST")
                        if self.next_run: # 执行下一个任务
                            self.next_run = False
                            self.msg_queue.put("NEXT")
                        if self.isFirst: # 移动到第一个点
                            self.isFirst = False
                            self.msg_queue.put("MOVE_FIRST")
                        if self.isZero: # 移动到第一个点
                            self.isZero = False
                            self.msg_queue.put("MOVE_ZERO")

        def startRun(self):
            " 开始执行"
            self.start_run = True

        def firstRun(self):
            "第一个位置处执行"
            self.start_run = True
            self.first_run = True

        def selectRun(self):
            "选择处执行"
            self.start_run = True
            self.select_run= True

        def pauseRun(self):
            "暂停"
            self.start_run = True
            self.isPause = True

        def continueRun(self):
            "继续"
            self.start_run = True
            self.continue_run = True

        def moveToZeroPos(self):
            "移动到第一个点位置"
            self.start_run = True
            self.isZero = True

        def moveToFirstPos(self):
            "移动到第一个点位置"
            self.start_run = True
            self.isFirst = True

        def nextRun(self):
            "开始下一个任务"
            self.start_run = True
            self.next_run = True
            self.step += 1

        def runTask(self):
            "执行当前任务"
    #
    # def saveData(self):
    #     timetest = time.strftime("%Y%m%d%H%M%S", time.localtime())
    #     name = QInputDialog.getText(self, "保存数据","任务名称:",QLineEdit.Normal, "%s_测试1"%timetest)
    #     if name[1]:
    #         if helper.find_mkdir('%s/%s'%(SAVE_PATH_DATA,name[0])):
    #             QMessageBox.information(self, "消息", "保存成功", QMessageBox.Yes | QMessageBox.No)
    #             helper.move_files(SAVE_PATH_TEMP,'%s/%s/'%(SAVE_PATH_DATA,name[0]))
    #         else:
    #             QMessageBox.information(self, "消息", "保存文件夹创建失败,请重新设置任务文件夹名称!", QMessageBox.Yes)

    def HexToNeg(self, hex_str):
        if hex_str[0] == 'F' or hex_str[0] == 'f':
            return int(hex_str,16)-(1<<32)
        else:
            return int(hex_str,16)

    def continueMeasure(self,data):
        '''连续测量数据处理'''
        print("数据包",data)
        if data == 'FF':# 走步任务完成
            print("连续测量任务完成")
            # self.move_flag = True
            return
        else:
            data = data[2:]
            t1 = self.HexToNeg(data[-16:-8])
            t2 = self.HexToNeg(data[-8:])
            x = self.HexToNeg(data[2:10])
            y = self.HexToNeg(data[12:20])
            z = self.HexToNeg(data[22:30])
            self.real_x = float('%.5f'%(x/PULSE_MM))
            self.real_y = float('%.5f'%(y/PULSE_MM))
            self.real_z = float('%.5f'%(z/PULSE_MM))
            self.signalOpengl.emit(self.real_x,self.real_y,self.real_z)
            t = self.task_current
            self.progress_value += 1
            self.signalProgress.emit(self.task_cnt,self.progress_value)
            # pdd测试断点
            # for i in range(0,len(data_pdd)):
                # z = int(self.real_z)
                # if abs(z - data_pdd[i][0])<1:
                    # t1 = data_pdd[i][1]
                    # t2 = data_pdd[i][2]
                    # break
            # pdd/oar测试数据
            # for d in data_pdd:
                # if t['type'] == 'PDD':
                    # if self.real_z == d[2]:
                        # t1 = d[3]
                        # t2 = d[4]
                        # break
                # if t['type'] == 'OAR':
                    # if self.real_x == d[0] and self.real_x == d[1]:
                        # t1 = d[3]
                        # t2 = d[4]
                        # break
            # 添加一次数据
            timetest = time.strftime("%Y:%m:%d-%H:%M:%S", time.localtime())
            # print(t)
            if t['rayType'] == '光子':
                self.pddoarList.append([timetest,self.real_x,self.real_y,self.real_z,t2,t1])
                self.dataTab.add_data(x=self.real_x,y=self.real_y,z=self.real_z,t1=t2,t2=t1)
            else:
                self.pddoarList.append([timetest,self.real_x,self.real_y,self.real_z,t1,t2])
                self.dataTab.add_data(x=self.real_x,y=self.real_y,z=self.real_z,t1=t1,t2=t2)
            # return
            # 加速器异常停止
            if len(self.pddoarList)>1:
                if abs(self.pddoarList[-2][-1] - self.pddoarList[-1][-1]) > slave_change_threshold:
                    self.pauseMove()
                    # print('加速器异常！！！')
                    #紧急停止
                    # cmd = WATER_CMD['移动停止']
                    # cmd[4] = ''
                    # self.cmd_send(cmd)
                    # self.stop_flag = True
                    return
            if self.measure_flag:
                if t['type'] == 'PDD':
                    data = self.pddoarList
                    self.signalTunnel.emit([d[3] for d in data],[d[4] for d in data],[d[5] for d in data])
                    return
                if t['type'] == 'OAR':
                    data = self.pddoarList
                    if t['direction'] == 'G->T' or t['direction'] == 'T->G':
                        self.signalTunnel.emit([d[2] for d in data],[d[4] for d in data],[d[5] for d in data])
                    else:
                        self.signalTunnel.emit([d[1] for d in data],[d[4] for d in data],[d[5] for d in data])
                    return
                if t['type'] == 'SCAN':
                    data = self.pddoarList
                    x = [d[1] for d in data]
                    y = [d[2] for d in data]
                    z = [d[5] for d in data]
                    z = [i*100/max(z) for i in z]
                    size = max(float(re.search(r'([0-9]+)',t['raySizeX']).group(0)),
                                float(re.search(r'([0-9]+)',t['raySizeY']).group(0)))
                    self.graphScan.updateSurface(x, y, z, size)
                    return

    def stepMove(self,data):
        if data == 'FF':# 走位完成
            # self.move_flag = True
            print("移动走位完成")
            self.signalOpengl.emit(self.real_x,self.real_y,self.real_z)
            if self.task_move_first_flag:
                # self.cmd_RunTask(self.task_current)
                self.taskRunThread.continueRun()
                print("继续执行")
                self.task_move_first_flag = False
            return
        data = data[2:]
        x = self.HexToNeg(data[2:10])
        y = self.HexToNeg(data[12:20])
        z = self.HexToNeg(data[22:30])
        self.real_x = x/PULSE_MM
        self.real_y = y/PULSE_MM
        self.real_z = z/PULSE_MM
        self.signalOpengl.emit(self.real_x,self.real_y,self.real_z)

    def get_axis(self,road,t,direction):
        '''生成坐标
        road:路线
        t：判断pdd或者oar
        direction: 方向
        '''
        r_pre = [0,0,0,0,0,0]
        r_now = None
        axis_list = []
        for i in range(0,len(road)):
            r_now = road[i]
            err_x = r_now[0] - r_pre[0]
            err_y = r_now[1] - r_pre[1]
            err_z = r_now[2] - r_pre[2]
            step_x = r_now[3]
            step_y = r_now[4]
            step_z = r_now[5]
            x_now = r_now[0]
            y_now = r_now[1]
            z_now = r_now[2]
            def return_axis(err,step,pre,now):
                if step>0:
                    axis = []
                    if err>0:
                        for i in range(0,abs(int(err/step))+1):
                            axis.append(pre+i*step)
                    else:
                        for i in range(0,abs(int(err/step))+1):
                            axis.append(pre-i*step)
                    axis.append(now)
                    return axis
            if t == 'pdd':
                z = return_axis(err_z,step_z,r_pre[2],r_now[2])
                if z:
                    for n in range(0,len(z)):
                        axis_list.append([0,0,z[n]])
                        if len(axis_list)>1 and axis_list[-1] == axis_list[-2]:
                            del axis_list[-1]
            if t == 'oar':
                if direction == 'A->B' or direction == 'B->A':
                    x = return_axis(err_x,step_x,r_pre[0],r_now[0])
                    if x:
                        for n in range(0,len(x)):
                            axis_list.append([x[n],y_now,z_now])
                            if len(axis_list)>1 and axis_list[-1] == axis_list[-2]:
                                del axis_list[-1]
                elif direction == 'G->T' or direction == 'T->G':
                    y = return_axis(err_y,step_y,r_pre[1],r_now[1])
                    if y:
                        for n in range(0,len(y)):
                            axis_list.append([x_now,y[n],z_now])
                            if len(axis_list)>1 and axis_list[-1] == axis_list[-2]:
                                del axis_list[-1]
                else:
                    x = return_axis(err_x,step_x,r_pre[0],r_now[0])
                    y = return_axis(err_y,step_y,r_pre[1],r_now[1])
                    if x:
                        for n in range(0,len(x)):
                            axis_list.append([x[n],y[n],z_now])
                            if len(axis_list)>1 and axis_list[-1] == axis_list[-2]:
                                del axis_list[-1]
            r_pre = road[i]
        return axis_list

    def cmd_RunTask(self,task):
        '''发送执行任务命令'''
        road = task['road']
        # self.signalOpenglRoad.emit(road)
        # self.send_task_axis(road)
        # 将负数转换成十六进制
        tohex = lambda val,nbits: hex((val + (1 << nbits)) % (1 << nbits))
        cmd_axis = hex(int(abs(len(road)))).replace('0x','').zfill(4).upper()
        for a in road:
            data_x = tohex(int(a[0]*10),16).replace('0x','').zfill(4).upper()
            data_y = tohex(int(a[1]*10),16).replace('0x','').zfill(4).upper()
            data_z = tohex(int(a[2]*10),16).replace('0x','').zfill(4).upper()
            cmd_axis += data_x + data_y + data_z
        cmd = WATER_CMD['任务坐标']
        cmd[4] = cmd_axis
        if DEBUG:
            print('发送任务坐标',road)
        self.cmd_send(cmd)
        self.dataTab.clear_data()

    def cmd_backZero(self):
        '''回到原点'''
        self.task_move_first_flag = False
        self.motorMoveAxis_position(0,0,0)

    def send_task_axis(self,axis):
        '''
        发送坐标任务命令
        axis:坐标集合,[[x,y,z] , ...]
        '''

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    # win = DeviceInputDlg()
    # win = ScanDialog()
    win = MainWindow()
    # win = TaskListWidget()
    # win = PddDialog()
    # win = OarDialog()
    win.show()
    app.exec_()

